diff --git a/CHANGELOG.md b/CHANGELOG.md index 94622a9..e276d3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,30 @@ # checkov-jetbrains-idea Changelog -## [Unreleased] -## [0.0.11-beta] -## [0.0.10-beta] -## [0.0.9-beta] -## [0.0.6-beta] -## [0.0.5-beta] +## [1.0.21] - 2024-08-29 + +### Added + +- Added the following data to Prisma Cloid analytics + + - Extension version + - VS Code version + - Operating system + - Checkov version + +### Fixed + +- Fixed installation issues with pip when using externally managed python installation +- Stabilized build time of the application and added support for multiple IDE versions +- Fixed various crashes + ## [0.0.3-beta] ### Added -* updated platform build range + +* Updated platform build range +* + ## [0.0.1] ### Added + - Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template) diff --git a/build.gradle.kts b/build.gradle.kts index 1860b4d..2e4a587 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent import org.jetbrains.changelog.markdownToHTML import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask fun properties(key: String) = project.findProperty(key).toString() @@ -9,16 +10,16 @@ plugins { // Java support id("java") // Kotlin support - id("org.jetbrains.kotlin.jvm") version "1.8.0" + id("org.jetbrains.kotlin.jvm") version "1.9.25" // gradle-intellij-plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin - id("org.jetbrains.intellij") version "1.10.1" + id("org.jetbrains.intellij") version "1.17.4" // gradle-changelog-plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin id("org.jetbrains.changelog") version "1.3.1" // Gradle Qodana Plugin id("org.jetbrains.qodana") version "0.1.13" // ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle id("org.jlleitschuh.gradle.ktlint") version "10.2.0" - kotlin("plugin.serialization") version "1.8.0" + kotlin("plugin.serialization") version "1.9.25" } group = properties("pluginGroup") @@ -27,21 +28,20 @@ version = properties("pluginVersion") // Configure project's dependencies repositories { mavenCentral() - jcenter() } + dependencies { implementation("com.beust:klaxon:5.6") implementation("com.google.code.gson:gson:2.10.1") - implementation("org.json:json:20230227") + implementation("org.json:json:20231013") implementation("commons-io:commons-io:2.11.0") implementation("io.github.java-diff-utils:java-diff-utils:4.12") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") - testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1") - testImplementation("org.junit.platform:junit-platform-engine:1.9.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter:5.8.1") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.9.0") } - // Configure gradle-intellij-plugin plugin. // Read more: https://github.com/JetBrains/gradle-intellij-plugin intellij { @@ -79,6 +79,10 @@ tasks { } } + withType().configureEach { + enabled = false + } + wrapper { gradleVersion = properties("gradleVersion") } @@ -142,6 +146,6 @@ tasks { } runPluginVerifier { - ideVersions.set(listOf("IC-2020.3.4", "IC-2021.1.3", "IC-2021.2.4")) + ideVersions.set(listOf("IC-2020.3.4", "IC-2021.1.3", "IC-2021.2.4", "IC-2024.1.6")) } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 17a771f..2413e14 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,14 +3,14 @@ pluginGroup = com.github.bridgecrewio.prismajetbrainsidea pluginName = prismacloud-jetbrains-idea -pluginVersion = 1.0.18 -pluginSinceBuild = 203 +pluginVersion=1.0.21 +pluginSinceBuild=241 # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl # See https://jb.gg/intellij-platform-builds-list for available build versions -pluginVerifierIdeVersions = 2020.3.4, 2021.1.3, 2021.2.4 +pluginVerifierIdeVersions=2020.3.4, 2021.1.3, 2021.2.4, 2024.1.6 platformType = IC -platformVersion = 2021.2.4 +platformVersion=2024.1.6 platformDownloadSources = true # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 @@ -21,7 +21,7 @@ platformPlugins = kotlin.stdlib.default.dependency = false # Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3 -javaVersion = 11 +javaVersion=17 # Gradle Releases -> https://github.com/gradle/gradle/releases -gradleVersion = 7.3 \ No newline at end of file +gradleVersion=7.6.4 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a9715..3994438 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt b/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt index fe23b72..a40d2b9 100644 --- a/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt +++ b/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt @@ -31,7 +31,6 @@ class PostStartupActivity : StartupActivity { project.service().startSchedulerReleasingAnalytics() // project.service().setMockCheckovResultsFromExampleFile() // MOCK } - }) PluginInstaller.addStateListener(object : PluginStateListener { @@ -69,4 +68,4 @@ class PostStartupActivity : StartupActivity { private fun sendAnalyticsPluginUninstalled(project: Project){ project.service().pluginUninstalled() } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsDataEvents.kt b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsDataEvents.kt index 2ddf0e7..722e4d5 100644 --- a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsDataEvents.kt +++ b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsDataEvents.kt @@ -1,19 +1,41 @@ package com.bridgecrew.analytics +import com.bridgecrew.cache.InMemCache import com.bridgecrew.settings.PLUGIN_NAME import com.bridgecrew.settings.PrismaSettingsState import com.google.gson.annotations.Expose -import kotlinx.serialization.* -import java.util.* +import com.intellij.ide.plugins.PluginManagerCore +import com.intellij.openapi.application.ApplicationInfo +import com.intellij.openapi.extensions.PluginId +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient import kotlinx.serialization.json.JsonObject +import java.util.* @OptIn(ExperimentalSerializationApi::class) @Serializable -sealed class AnalyticsData(@EncodeDefault val pluginName: String = PLUGIN_NAME){ +sealed class AnalyticsData(@EncodeDefault val pluginName: String = PLUGIN_NAME) { + @EncodeDefault val installationId: String = PrismaSettingsState().getInstance()!!.installationId + @EncodeDefault + var pluginVersion: String? = + PluginManagerCore.getPlugin(PluginId.getId("com.github.bridgecrewio.prismacloud"))?.version + + @EncodeDefault + var ideVersion: String? = + ApplicationInfo.getInstance().fullApplicationName + " / " + ApplicationInfo.getInstance().build + + @EncodeDefault + var operatingSystem: String? = System.getProperty("os.name") + " " + System.getProperty("os.version") + + @EncodeDefault + var checkovVersion: String? = InMemCache.get("checkovVersion") + @Serializable lateinit var eventType: String @@ -51,8 +73,7 @@ data class FullScanAnalyticsData(@Transient val scanNumber: Int = 0): AnalyticsD @OptIn(ExperimentalSerializationApi::class) @Serializable data class PluginInstallAnalyticsData( - @EncodeDefault - override val eventData: JsonObject = JsonObject(mapOf()) + @EncodeDefault override val eventData: JsonObject = JsonObject(mapOf()) ) : AnalyticsData() @Serializable @@ -63,4 +84,4 @@ data class FullScanFrameworkScanTimeData( @Serializable(with = DateSerializer::class) var endTime: Date = Date() var totalTimeSeconds = 0L -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt index 4ae1485..7a3d2ee 100644 --- a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt +++ b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt @@ -10,11 +10,12 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.project.Project -import kotlinx.serialization.* +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.TimeUnit -import kotlinx.serialization.json.Json @Service @@ -211,4 +212,4 @@ class AnalyticsService(val project: Project) { analyticsData.eventType = EventTypeEnum.ON_PLUGIN_UNINSTALL analyticsEventData.add(Json.encodeToString(analyticsData)) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/api/ApiClient.kt b/src/main/kotlin/com/bridgecrew/api/ApiClient.kt index d462c11..327cc44 100644 --- a/src/main/kotlin/com/bridgecrew/api/ApiClient.kt +++ b/src/main/kotlin/com/bridgecrew/api/ApiClient.kt @@ -4,8 +4,11 @@ package com.bridgecrew.api import com.bridgecrew.settings.DEFAULT_REPORTING_INTERVAL import com.bridgecrew.settings.PLUGIN_NAME import com.intellij.openapi.diagnostic.logger -import kotlinx.serialization.* -import kotlinx.serialization.json.* +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import java.io.IOException import java.net.URI import java.net.http.HttpClient @@ -135,4 +138,4 @@ class ApiClient(private val username: String, private val password: String, priv return LoginResponse("") } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt b/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt index 960775c..e4b52c1 100644 --- a/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt +++ b/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt @@ -2,8 +2,9 @@ package com.bridgecrew.cache import com.intellij.openapi.project.Project -class CacheDataAnalytics (private val project: Project){ - fun load(analyticsEventData: MutableList){ +class CacheDataAnalytics(private val project: Project) { + + fun load(analyticsEventData: MutableList) { val data = CacheDataAnalyticsStorage(project).readDataFromFile() if(data.isNullOrEmpty()){ return @@ -15,8 +16,8 @@ class CacheDataAnalytics (private val project: Project){ CacheDataAnalyticsStorage(project).clear() } - fun stash(analyticsEventData: MutableList){ + fun stash(analyticsEventData: MutableList) { val data = analyticsEventData.joinToString("\n") CacheDataAnalyticsStorage(project).writeDataToFile(data) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/cache/InMemCache.kt b/src/main/kotlin/com/bridgecrew/cache/InMemCache.kt new file mode 100644 index 0000000..5c896a1 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/cache/InMemCache.kt @@ -0,0 +1,14 @@ +package com.bridgecrew.cache + +object InMemCache { + + private val cache: MutableMap = mutableMapOf() + + fun get(key: String): String? { + return cache[key] + } + + fun set(key: String, value: String) { + cache[key] = value + } +} diff --git a/src/main/kotlin/com/bridgecrew/initialization/InitializationService.kt b/src/main/kotlin/com/bridgecrew/initialization/InitializationService.kt index 01ae0a3..bc1b862 100644 --- a/src/main/kotlin/com/bridgecrew/initialization/InitializationService.kt +++ b/src/main/kotlin/com/bridgecrew/initialization/InitializationService.kt @@ -2,9 +2,9 @@ package com.bridgecrew.initialization import CheckovInstallerService import CliService +import com.bridgecrew.cache.InMemCache import com.bridgecrew.listeners.CheckovInstallerListener import com.bridgecrew.listeners.InitializationListener -import com.bridgecrew.services.scan.CheckovScanService import com.bridgecrew.services.checkovScanCommandsService.CheckovScanCommandsService import com.bridgecrew.services.checkovScanCommandsService.DockerCheckovScanCommandsService import com.bridgecrew.services.checkovScanCommandsService.InstalledCheckovScanCommandsService @@ -12,6 +12,7 @@ import com.bridgecrew.services.installation.DockerInstallerCommandService import com.bridgecrew.services.installation.InstallerCommandService import com.bridgecrew.services.installation.PipInstallerCommandService import com.bridgecrew.services.installation.PipenvInstallerCommandService +import com.bridgecrew.services.scan.CheckovScanService import com.bridgecrew.utils.initializeRepoName import com.intellij.openapi.components.Service import com.intellij.openapi.components.service @@ -25,7 +26,7 @@ private val LOG = logger() class InitializationService(private val project: Project) { private var isCheckovInstalledGlobally: Boolean = false - private var checkovVersion: String = "3.2.20" + private var minimalCheckovVersion: String = "3.2.20" fun initializeProject() { initializeCheckovScanService() @@ -46,6 +47,7 @@ class InitializationService(private val project: Project) { if (output.lowercase().trim().contains("pulling from bridgecrew/checkov") || !checkIfCheckovUpdateNeeded(output)) { + LOG.info("Docker picked for Checkov installation") setSelectedCheckovService(DockerCheckovScanCommandsService(project)) return } @@ -54,16 +56,17 @@ class InitializationService(private val project: Project) { } private fun installCheckovIfNeededAndSetCheckovPath() { - project.messageBus.connect() - .subscribe(CheckovInstallerListener.INSTALLER_TOPIC, object : CheckovInstallerListener { - override fun installerFinished(serviceClass: InstallerCommandService) { - if (serviceClass is PipenvInstallerCommandService) { - updateCheckovPathAfterInstallation() - } else { - setSelectedCheckovServiceFromInstaller(serviceClass) - } + project.messageBus.connect().subscribe(CheckovInstallerListener.INSTALLER_TOPIC, + object : CheckovInstallerListener { + override fun installerFinished(serviceClass: InstallerCommandService) { + if (serviceClass is PipenvInstallerCommandService) { + updateCheckovPathAfterInstallation() + } else { + setSelectedCheckovServiceFromInstaller(serviceClass) } - }) + } + } + ) LOG.info("Checking global checkov installation with `checkov`") val isGloballyInstalledCommand = arrayListOf("checkov", "-v") @@ -107,8 +110,6 @@ class InitializationService(private val project: Project) { val command = PipInstallerCommandService.getUnixCommandsForFindingCheckovPath() project.service().run(command, project, this::updatePathUnix) } - - } private fun updatePathUnix(output: String, exitCode: Int, project: Project) { @@ -225,8 +226,8 @@ class InitializationService(private val project: Project) { private fun checkIfCheckovUpdateNeeded(rawVersion: String): Boolean { val version = rawVersion.split('\n')[0] LOG.info("Checkov version $version") - - return !versionIsNewer(version, checkovVersion) + InMemCache.set("checkovVersion", version) + return !versionIsNewer(version, minimalCheckovVersion) } private fun updateCheckovPip(project: Project) { @@ -238,6 +239,7 @@ class InitializationService(private val project: Project) { project.service().run(cmds, project, this::onCheckovUpdate, this::onCheckovUpdate) } + @Suppress("UNUSED_PARAMETER") private fun onCheckovUpdate(output: String, exitCode: Int, project: Project) { if (exitCode != 0) { LOG.warn("Failed to pull Checkov image") @@ -248,4 +250,4 @@ class InitializationService(private val project: Project) { setSelectedCheckovService(DockerCheckovScanCommandsService(project)) LOG.info("Checkov Docker updated") } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/listeners/CheckovInstallerListener.kt b/src/main/kotlin/com/bridgecrew/listeners/CheckovInstallerListener.kt index ddc389c..ba414dd 100644 --- a/src/main/kotlin/com/bridgecrew/listeners/CheckovInstallerListener.kt +++ b/src/main/kotlin/com/bridgecrew/listeners/CheckovInstallerListener.kt @@ -5,8 +5,7 @@ import com.intellij.util.messages.Topic interface CheckovInstallerListener { companion object { - val INSTALLER_TOPIC = - Topic.create("Checkov installer", CheckovInstallerListener::class.java) + val INSTALLER_TOPIC = Topic.create("Checkov installer", CheckovInstallerListener::class.java) } fun installerFinished(serviceClass: InstallerCommandService) diff --git a/src/main/kotlin/com/bridgecrew/services/CliService.kt b/src/main/kotlin/com/bridgecrew/services/CliService.kt index e77e3cb..d0db12b 100644 --- a/src/main/kotlin/com/bridgecrew/services/CliService.kt +++ b/src/main/kotlin/com/bridgecrew/services/CliService.kt @@ -61,8 +61,8 @@ class CliService { title: String, val processHandler: ProcessHandler, val function: (output: String, exitCode: Int, project: Project) -> Unit, - ) : - Task.Backgroundable(project, title,true) { + ) : Task.Backgroundable(project, title, true) { + override fun run(indicator: ProgressIndicator) { indicator.isIndeterminate = false try { @@ -70,8 +70,7 @@ class CliService { ScriptRunnerUtil.STDOUT_OR_STDERR_OUTPUT_KEY_FILTER, 720000000) function(output, processHandler.exitCode!!, project) - } - catch (e: Exception) { + } catch (e: Exception) { if (e.message?.contains("Script execution took") == true){ CheckovNotificationBalloon.showNotification(project, "Exceeded allocated scanning time", @@ -84,7 +83,6 @@ class CliService { } } - } diff --git a/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/CheckovScanCommandsService.kt b/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/CheckovScanCommandsService.kt index 0345047..67b1371 100644 --- a/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/CheckovScanCommandsService.kt +++ b/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/CheckovScanCommandsService.kt @@ -2,9 +2,12 @@ package com.bridgecrew.services.checkovScanCommandsService import com.bridgecrew.listeners.CheckovSettingsListener import com.bridgecrew.settings.PrismaSettingsState -import com.bridgecrew.utils.* +import com.bridgecrew.utils.FULL_SCAN_EXCLUDED_PATHS +import com.bridgecrew.utils.getGitIgnoreValues +import com.bridgecrew.utils.getRepoName +import com.bridgecrew.utils.isWindows import com.intellij.openapi.project.Project -import org.apache.commons.lang.StringUtils +import org.apache.commons.lang3.StringUtils abstract class CheckovScanCommandsService(val project: Project) { protected val settings = PrismaSettingsState().getInstance() @@ -110,5 +113,4 @@ abstract class CheckovScanCommandsService(val project: Project) { abstract fun getFilePath(originalFilePath: String): String abstract fun getCertPath(): String abstract fun getOutputFilePath(outputFilePath: String): String - -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/DockerCheckovScanCommandsService.kt b/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/DockerCheckovScanCommandsService.kt index 4280d3c..3207e91 100644 --- a/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/DockerCheckovScanCommandsService.kt +++ b/src/main/kotlin/com/bridgecrew/services/checkovScanCommandsService/DockerCheckovScanCommandsService.kt @@ -12,9 +12,9 @@ class DockerCheckovScanCommandsService(project: Project) : CheckovScanCommandsSe private val image = "bridgecrew/checkov" private val volumeDirectory = getDockerUnixPath(project.basePath) private val volumeCertPath = "/usr/lib/ssl/cert.pem" + override fun getCheckovRunningCommandByServiceType(outputFilePath: String): ArrayList { - val pluginVersion = - PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID))?.version ?: "UNKNOWN" + val pluginVersion = PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID))?.version ?: "UNKNOWN" val dockerCommand = arrayListOf("docker", "run", "--rm", "-a", "stdout", "-a", "stderr", "--env", "BC_SOURCE=jetbrains", "--env", "BC_SOURCE_VERSION=$pluginVersion", "--env", "LOG_LEVEL=DEBUG") val prismaUrl = settings?.prismaURL @@ -33,7 +33,6 @@ class DockerCheckovScanCommandsService(project: Project) : CheckovScanCommandsSe val volumeDir = "${FilenameUtils.separatorsToUnix(project.basePath)}:/${volumeDirectory}" dockerCommand.addAll(arrayListOf("--volume", volumeDir, image)) return dockerCommand - } override fun getDirectory(): String { @@ -56,4 +55,4 @@ class DockerCheckovScanCommandsService(project: Project) : CheckovScanCommandsSe override fun getCertPath(): String { return volumeCertPath } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/services/installation/DockerInstallerCommandService.kt b/src/main/kotlin/com/bridgecrew/services/installation/DockerInstallerCommandService.kt index a2c0b48..685340c 100644 --- a/src/main/kotlin/com/bridgecrew/services/installation/DockerInstallerCommandService.kt +++ b/src/main/kotlin/com/bridgecrew/services/installation/DockerInstallerCommandService.kt @@ -1,11 +1,12 @@ package com.bridgecrew.services.installation +import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.openapi.project.Project class DockerInstallerCommandService : InstallerCommandService { - override fun getInstallCommand(): ArrayList { - return arrayListOf("docker", "pull", "bridgecrew/checkov") + override fun getInstallCommand(): GeneralCommandLine { + return GeneralCommandLine(arrayListOf("docker", "pull", "bridgecrew/checkov")) } override fun getVersion(project: Project): ArrayList { diff --git a/src/main/kotlin/com/bridgecrew/services/installation/InstallService.kt b/src/main/kotlin/com/bridgecrew/services/installation/InstallService.kt index 757fe27..ff204ee 100644 --- a/src/main/kotlin/com/bridgecrew/services/installation/InstallService.kt +++ b/src/main/kotlin/com/bridgecrew/services/installation/InstallService.kt @@ -3,7 +3,6 @@ import com.bridgecrew.services.installation.DockerInstallerCommandService import com.bridgecrew.services.installation.InstallerCommandService import com.bridgecrew.services.installation.PipInstallerCommandService import com.bridgecrew.services.installation.PipenvInstallerCommandService -import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.process.ProcessHandler import com.intellij.execution.process.ScriptRunnerUtil @@ -31,8 +30,7 @@ class CheckovInstallerService { val checkovServices = arrayOf(DockerInstallerCommandService(), PipInstallerCommandService(), PipenvInstallerCommandService()) for (service in checkovServices) { try { - val command = service.getInstallCommand() - val generalCommandLine = GeneralCommandLine(command) + val generalCommandLine = service.getInstallCommand() generalCommandLine.charset = Charset.forName("UTF-8") val processHandler: ProcessHandler = OSProcessHandler(generalCommandLine) commands.add(Pair(service, processHandler)) @@ -44,8 +42,7 @@ class CheckovInstallerService { if (commands.isEmpty()) { LOG.error("Checkov could not be installed, your machine is missing all 3 installation options.\n Please install docker | pip | pipenv") } - val installerTask = - InstallerTask(project, "Installing checkov", commands) + val installerTask = InstallerTask(project, "Installing checkov", commands) if (SwingUtilities.isEventDispatchThread()) { ProgressManager.getInstance().run(installerTask) } else { @@ -55,8 +52,12 @@ class CheckovInstallerService { } } - private class InstallerTask(project: Project, title: String, val services: ArrayList>) : - Task.Backgroundable(project, title, true) { + private class InstallerTask( + project: Project, + title: String, + val services: ArrayList> + ) : Task.Backgroundable(project, title, true) { + override fun run(indicator: ProgressIndicator) { indicator.isIndeterminate = false for (service in services) { diff --git a/src/main/kotlin/com/bridgecrew/services/installation/InstallerCommandService.kt b/src/main/kotlin/com/bridgecrew/services/installation/InstallerCommandService.kt index 802ecde..273e254 100644 --- a/src/main/kotlin/com/bridgecrew/services/installation/InstallerCommandService.kt +++ b/src/main/kotlin/com/bridgecrew/services/installation/InstallerCommandService.kt @@ -1,8 +1,9 @@ package com.bridgecrew.services.installation +import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.openapi.project.Project interface InstallerCommandService { - fun getInstallCommand(): ArrayList + fun getInstallCommand(): GeneralCommandLine fun getVersion(project: Project): ArrayList } \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/services/installation/PipInstallerCommandService.kt b/src/main/kotlin/com/bridgecrew/services/installation/PipInstallerCommandService.kt index e00987a..16fa5b8 100644 --- a/src/main/kotlin/com/bridgecrew/services/installation/PipInstallerCommandService.kt +++ b/src/main/kotlin/com/bridgecrew/services/installation/PipInstallerCommandService.kt @@ -1,13 +1,26 @@ package com.bridgecrew.services.installation import CliService +import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.openapi.components.service import com.intellij.openapi.project.Project class PipInstallerCommandService : InstallerCommandService { - override fun getInstallCommand(): ArrayList { - return arrayListOf("pip3", "install", "-U", "--user", "checkov", "-i", "https://pypi.org/simple/") + override fun getInstallCommand(): GeneralCommandLine { + val command = GeneralCommandLine( + arrayListOf( + "pip3", + "install", + "-U", + "--user", + "checkov", + "-i", + "https://pypi.org/simple/" + ) + ) + command.environment["PIP_BREAK_SYSTEM_PACKAGES"] = "1" + return command } override fun getVersion(project: Project): ArrayList { diff --git a/src/main/kotlin/com/bridgecrew/services/installation/PipenvInstallerCommandService.kt b/src/main/kotlin/com/bridgecrew/services/installation/PipenvInstallerCommandService.kt index 9724ce0..b73a7bf 100644 --- a/src/main/kotlin/com/bridgecrew/services/installation/PipenvInstallerCommandService.kt +++ b/src/main/kotlin/com/bridgecrew/services/installation/PipenvInstallerCommandService.kt @@ -1,13 +1,14 @@ package com.bridgecrew.services.installation import CliService +import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.openapi.components.service import com.intellij.openapi.project.Project class PipenvInstallerCommandService : InstallerCommandService { - override fun getInstallCommand(): ArrayList { - return arrayListOf("pipenv", "--python", "3", "install", "checkov") + override fun getInstallCommand(): GeneralCommandLine { + return GeneralCommandLine(arrayListOf("pipenv", "--python", "3", "install", "checkov")) } override fun getVersion(project: Project): ArrayList { diff --git a/src/main/kotlin/com/bridgecrew/services/scan/CheckovScanService.kt b/src/main/kotlin/com/bridgecrew/services/scan/CheckovScanService.kt index f173f96..aa07bb5 100644 --- a/src/main/kotlin/com/bridgecrew/services/scan/CheckovScanService.kt +++ b/src/main/kotlin/com/bridgecrew/services/scan/CheckovScanService.kt @@ -28,7 +28,6 @@ import com.intellij.openapi.project.Project import java.io.File import java.nio.charset.Charset import javax.swing.SwingUtilities -import kotlin.io.path.Path private val LOG = logger() @@ -111,7 +110,6 @@ class CheckovScanService: Disposable { val processHandler: ProcessHandler = OSProcessHandler.Silent(generateCheckovCommand(execCommand)) - val scanTask = ScanTask.FrameworkScanTask(project, "Prisma Cloud is scanning your repository by framework $framework", framework, processHandler, checkovResultFile) fullScanTasks.add(scanTask) project.service().fullScanByFrameworkStarted(framework) @@ -167,8 +165,7 @@ class CheckovScanService: Disposable { } private fun generateCheckovCommand(execCommand: List): GeneralCommandLine { - val pluginVersion = PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID))?.version - ?: "UNKNOWN" + val pluginVersion = PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID))?.version ?: "UNKNOWN" val prismaUrl = settings?.prismaURL val generalCommandLine = GeneralCommandLine(execCommand) diff --git a/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt b/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt index 6ccb2eb..afc86b6 100644 --- a/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt +++ b/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt @@ -190,4 +190,4 @@ class FullScanStateService(val project: Project) { SUCCESSFUL_SCAN, FAILED_SCAN } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsConfigurable.kt b/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsConfigurable.kt index aa4dbf7..f71c980 100644 --- a/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsConfigurable.kt +++ b/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsConfigurable.kt @@ -52,4 +52,4 @@ class PrismaSettingsConfigurable(val project: Project) : Configurable { prismaSettingsComponent.prismaURLField.text = setting?.prismaURL prismaSettingsComponent.fullScanRepoLimitField.value = setting?.fullScanRepoLimit } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsState.kt b/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsState.kt index f6cfa06..0d7739d 100644 --- a/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsState.kt +++ b/src/main/kotlin/com/bridgecrew/settings/PrismaSettingsState.kt @@ -9,7 +9,7 @@ import com.intellij.util.xmlb.XmlSerializerUtil const val PLUGIN_NAME = "jetbrains" // represents the time interval in seconds between sending statistic data from the client to the backend -const val DEFAULT_REPORTING_INTERVAL = 5 * 60; +const val DEFAULT_REPORTING_INTERVAL = 5 * 60 @State( @@ -53,4 +53,4 @@ class PrismaSettingsState : PersistentStateComponent { override fun loadState(state: PrismaSettingsState) { XmlSerializerUtil.copyBean(state, this) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/ui/actions/FixAction.kt b/src/main/kotlin/com/bridgecrew/ui/actions/FixAction.kt index 4e99870..08767ac 100644 --- a/src/main/kotlin/com/bridgecrew/ui/actions/FixAction.kt +++ b/src/main/kotlin/com/bridgecrew/ui/actions/FixAction.kt @@ -7,6 +7,7 @@ import com.bridgecrew.results.BaseCheckovResult import com.bridgecrew.results.Category import com.bridgecrew.results.VulnerabilityCheckovResult import com.bridgecrew.services.scan.CheckovScanService +import com.bridgecrew.settings.CheckovGlobalState import com.bridgecrew.utils.navigateToFile import com.intellij.ide.DataManager import com.intellij.openapi.application.ApplicationManager @@ -16,46 +17,47 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.ui.Messages import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import java.awt.event.ActionEvent import java.awt.event.ActionListener import javax.swing.JButton -import com.bridgecrew.settings.CheckovGlobalState -import com.intellij.openapi.ui.Messages class FixAction(private val buttonInstance: JButton, val result: BaseCheckovResult) : ActionListener { init { - val dataContext = DataManager.getInstance().dataContext - val project = dataContext.getData("project") as Project - val connection = project.messageBus.connect() - val inScanMsg = "Scan in progress. Please wait for completion before retrying." - buttonInstance.isEnabled = !CheckovGlobalState.scanInProgress - connection.subscribe(CheckovScanListener.SCAN_TOPIC, object : CheckovScanListener { - override fun fileScanningStarted(){ - buttonInstance.isEnabled = false - buttonInstance.toolTipText = inScanMsg - CheckovGlobalState.scanInProgress = true - } - override fun projectScanningStarted(){ - buttonInstance.isEnabled = false - buttonInstance.toolTipText = inScanMsg - CheckovGlobalState.scanInProgress = true - } - override fun scanningFinished(scanSourceType: CheckovScanService.ScanSourceType){ - buttonInstance.isEnabled = true - buttonInstance.toolTipText = "" - CheckovGlobalState.scanInProgress = false - } - override fun fullScanFailed(){ - buttonInstance.isEnabled = true - buttonInstance.toolTipText = "" - CheckovGlobalState.scanInProgress = false - } - }) + DataManager.getInstance().dataContextFromFocusAsync.then { dataContext -> + val project = dataContext.getData("project") as Project + val connection = project.messageBus.connect() + val inScanMsg = "Scan in progress. Please wait for completion before retrying." + buttonInstance.isEnabled = !CheckovGlobalState.scanInProgress + connection.subscribe(CheckovScanListener.SCAN_TOPIC, object : CheckovScanListener { + override fun fileScanningStarted() { + buttonInstance.isEnabled = false + buttonInstance.toolTipText = inScanMsg + CheckovGlobalState.scanInProgress = true + } + + override fun projectScanningStarted() { + buttonInstance.isEnabled = false + buttonInstance.toolTipText = inScanMsg + CheckovGlobalState.scanInProgress = true + } + override fun scanningFinished(scanSourceType: CheckovScanService.ScanSourceType) { + buttonInstance.isEnabled = true + buttonInstance.toolTipText = "" + CheckovGlobalState.scanInProgress = false + } + override fun fullScanFailed() { + buttonInstance.isEnabled = true + buttonInstance.toolTipText = "" + CheckovGlobalState.scanInProgress = false + } + }) + } } private val LOG = logger() @@ -86,14 +88,16 @@ class FixAction(private val buttonInstance: JButton, val result: BaseCheckovResu val startOffset = document!!.getLineStartOffset(startLine) val endOffset = document.getLineEndOffset(endLine) - val dataContext = DataManager.getInstance().dataContext - val project = dataContext.getData("project") as Project + DataManager.getInstance().dataContextFromFocusAsync.then { dataContext -> + val project = dataContext.getData("project") as Project - WriteCommandAction.runWriteCommandAction(project) { - document.replaceString(startOffset, endOffset, result.fixDefinition!!) - FileDocumentManager.getInstance().saveDocument(document) - navigateToFile(project, virtualFile, result.codeDiffFirstLine) + WriteCommandAction.runWriteCommandAction(project) { + document.replaceString(startOffset, endOffset, result.fixDefinition!!) + FileDocumentManager.getInstance().saveDocument(document) + navigateToFile(project, virtualFile, result.codeDiffFirstLine) + } } + } catch (e: Exception) { LOG.warn("error while trying to apply fix", e) buttonInstance.isEnabled = true @@ -126,12 +130,14 @@ class FixAction(private val buttonInstance: JButton, val result: BaseCheckovResu } private fun showSCAFixModal(fixCommand: FixCommand, isSuccess: Boolean) { - val dataContext = DataManager.getInstance().dataContext - val project = dataContext.getData("project") as Project - Messages.showInfoMessage(project, + DataManager.getInstance().dataContextFromFocusAsync.then { dataContext -> + val project = dataContext.getData("project") as Project + Messages.showInfoMessage( + project, buildModalMessage(fixCommand, isSuccess), "SCA Fix - Additional Action Required" - ) + ) + } } private fun buildModalMessage(fixCommand: FixCommand, isSuccess: Boolean): String { @@ -148,4 +154,4 @@ class FixAction(private val buttonInstance: JButton, val result: BaseCheckovResu } return message } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/ui/actions/FocusOnFileInTree.kt b/src/main/kotlin/com/bridgecrew/ui/actions/FocusOnFileInTree.kt index 5843548..7c629b8 100644 --- a/src/main/kotlin/com/bridgecrew/ui/actions/FocusOnFileInTree.kt +++ b/src/main/kotlin/com/bridgecrew/ui/actions/FocusOnFileInTree.kt @@ -11,8 +11,10 @@ import java.awt.event.ActionListener class FocusOnFileInTree(val filePath: String) : ActionListener { override fun actionPerformed(e: ActionEvent?) { - val dataContext = DataManager.getInstance().dataContext - val project = dataContext.getData("project") as Project - project.service().loadMainPanel(PANELTYPE.CHECKOV_FILE_SCAN_FINISHED, filePath) + DataManager.getInstance().dataContextFromFocusAsync.then { dataContext -> + val project = dataContext.getData("project") as Project + project.service() + .loadMainPanel(PANELTYPE.CHECKOV_FILE_SCAN_FINISHED, filePath) + } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/bridgecrew/ui/errorBubble/CheckovErrorBubble.kt b/src/main/kotlin/com/bridgecrew/ui/errorBubble/CheckovErrorBubble.kt index e873695..38b9dcf 100644 --- a/src/main/kotlin/com/bridgecrew/ui/errorBubble/CheckovErrorBubble.kt +++ b/src/main/kotlin/com/bridgecrew/ui/errorBubble/CheckovErrorBubble.kt @@ -40,7 +40,7 @@ class CheckovErrorBubble(val project: Project, val results: List + vulnerabilityResults.sortedBy { it.severity }.forEach { vulnerabilityCheckovResult -> panelList.add(ErrorBubbleInnerPanel(project, vulnerabilityCheckovResult, 0, runningIndex, totalPanels, callBack)) runningIndex += 1 } @@ -81,4 +81,4 @@ class CheckovErrorBubble(val project: Project, val results: List().run(cmds, project, ::extractRepoNameFromOutput) } +@Suppress("UNUSED_PARAMETER") fun extractRepoNameFromOutput(output: String, exitCode: Int, project: Project) { try { val lines = output.split("\n") @@ -77,4 +78,4 @@ fun parseRepoName(repoUrl: String): String? { } return repoUrl.substring(maxOf(priorSlash, priorColon) + 1, repoUrl.lastIndexOf(".git")) -} \ No newline at end of file +} diff --git a/src/test/kotlin/com/bridgecrew/ui/rightPanel/dictionaryDetails/WeaknessDictionaryPanelTest.kt b/src/test/kotlin/com/bridgecrew/ui/rightPanel/dictionaryDetails/WeaknessDictionaryPanelTest.kt index 701b4b1..de4c001 100644 --- a/src/test/kotlin/com/bridgecrew/ui/rightPanel/dictionaryDetails/WeaknessDictionaryPanelTest.kt +++ b/src/test/kotlin/com/bridgecrew/ui/rightPanel/dictionaryDetails/WeaknessDictionaryPanelTest.kt @@ -1,11 +1,10 @@ package com.bridgecrew.ui.rightPanel.dictionaryDetails import com.bridgecrew.fixtures.* -import com.bridgecrew.fixtures.metadataTaintModeJson import com.intellij.mock.MockProject import com.intellij.openapi.util.Disposer import org.jetbrains.annotations.SystemIndependent -import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test