diff --git a/CHANGELOG.md b/CHANGELOG.md index 88ba0df..4ffd0ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ -# checkov-jetbrains-idea Changelog +# Prisma Cloud Changelog + +## [1.1.0] - 2024-09-23 ## [1.0.22] - 2024-09-15 diff --git a/build.gradle.kts b/build.gradle.kts index f32b470..3ada77c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ group = properties("pluginGroup") version = properties("pluginVersion") kotlin { - jvmToolchain(17) + jvmToolchain(properties("javaVersion").toInt()) } // Configure project's dependencies @@ -39,12 +39,10 @@ dependencies { implementation(libs.jackson) implementation(libs.springWeb) implementation("org.json:json:20231013") // TODO: Remove when possible - implementation(libs.commons) + implementation(libs.commonsLang) implementation(libs.slf4j) implementation(libs.logback) implementation(libs.diffUtils) - compileOnly(libs.lombok) - annotationProcessor(libs.lombok) testImplementation(libs.junit) testImplementation(libs.jupiterApi) testRuntimeOnly(libs.jupiter) @@ -134,7 +132,7 @@ tasks { withType { compilerOptions { jvmTarget = JvmTarget.fromTarget(it) - apiVersion = KotlinVersion.KOTLIN_1_8 + apiVersion = KotlinVersion.KOTLIN_2_0 } } } @@ -143,6 +141,10 @@ tasks { gradleVersion = properties("gradleVersion") } + build { + dependsOn(buildPlugin) + } + patchPluginXml { // Extract the section from README.md and provide for the plugin's manifest pluginDescription.set( @@ -202,4 +204,4 @@ intellijPlatformTesting { } } } -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 4ed79f4..3bf561e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,12 +3,12 @@ pluginGroup = com.github.bridgecrewio.prismajetbrainsidea pluginName = Prisma Cloud -pluginVersion=1.0.22 +pluginVersion=1.1.0 platformType = IC # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html -pluginSinceBuild=203 -platformVersion=2023.3.8 +pluginSinceBuild=231 +platformVersion=2023.1.7 platformDownloadSources = true # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 @@ -20,9 +20,8 @@ platformBundledPlugins= # See https://kotlinlang.org/docs/reference/using-gradle.html#dependency-on-the-standard-library for details. 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 -# TODO: Change to 21 on next version -javaVersion=11 +# Java language level used to compile sources and to generate the files for +javaVersion=17 # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion=8.10.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b268ae6..509e6c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,8 +3,8 @@ # libraries jackson = "2.17.2" lombok = "1.18.34" -springWeb = "5.3.39" # TODO: Change to 6.x.x when moving to Java 17+ -commons-io = "2.16.1" +springWeb = "6.1.13" +commons-lang3 = "3.17.0" slf4j = "2.0.16" logback = "1.5.6" diffUtils = "4.12" @@ -14,8 +14,8 @@ junitPlatform = "1.9.0" # plugins changelog = "2.2.1" -intelliJPlatform = "2.0.1" -kotlin = "1.8.22" # TODO: Change to 2.0.x on next version +intelliJPlatform = "2.1.0" +kotlin = "2.0.20" kover = "0.8.3" qodana = "0.1.13" @@ -23,7 +23,7 @@ qodana = "0.1.13" jackson = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jackson"} lombok = { group = "org.projectlombok", name = "lombok", version.ref = "lombok" } springWeb = { group = "org.springframework", name = "spring-web", version.ref = "springWeb" } -commons = { group = "commons-io", name = "commons-io", version.ref = "commons-io" } +commonsLang = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commons-lang3" } slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } logback = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" } diffUtils = { group = "io.github.java-diff-utils", name = "java-diff-utils", version.ref = "diffUtils" } diff --git a/src/main/java/com/bridgecrew/log/LoggerService.java b/src/main/java/com/bridgecrew/log/LoggerService.java index d33b1d8..90f6485 100644 --- a/src/main/java/com/bridgecrew/log/LoggerService.java +++ b/src/main/java/com/bridgecrew/log/LoggerService.java @@ -18,8 +18,8 @@ public String getLogFilePath() { LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); ch.qos.logback.classic.Logger rootLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); Appender appender = rootLogger.getAppender("FILE"); - if (appender instanceof FileAppender) { - return ((FileAppender)appender).getFile(); + if (appender instanceof FileAppender fileAppender) { + return fileAppender.getFile(); } return null; } diff --git a/src/main/java/com/bridgecrew/util/ApplicationServiceUtil.java b/src/main/java/com/bridgecrew/util/ApplicationServiceUtil.java deleted file mode 100644 index 4a43cec..0000000 --- a/src/main/java/com/bridgecrew/util/ApplicationServiceUtil.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.bridgecrew.util; - -import com.intellij.openapi.application.ApplicationManager; -import lombok.experimental.UtilityClass; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@UtilityClass -public class ApplicationServiceUtil { - - private static final Logger logger = LoggerFactory.getLogger(ApplicationServiceUtil.class); - - public static T getService(Class clazz) { - T service = ApplicationManager.getApplication().getService(clazz); - if (service == null) { - String message = String.format("Could not find service %s", clazz.getSimpleName()); - logger.error(message); - throw new IllegalArgumentException(message); - } - return service; - } -} diff --git a/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt b/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt index 13c6875..c1d67db 100644 --- a/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt +++ b/src/main/kotlin/com/bridgecrew/activities/PostStartupActivity.kt @@ -8,7 +8,7 @@ import com.bridgecrew.listeners.PrismaVirtualFileListener import com.bridgecrew.log.LoggerService import com.bridgecrew.settings.PrismaSettingsState import com.bridgecrew.ui.CheckovToolWindowManagerPanel -import com.bridgecrew.util.ApplicationServiceUtil +import com.bridgecrew.utils.ApplicationServiceUtil import com.intellij.ide.plugins.IdeaPluginDescriptor import com.intellij.ide.plugins.PluginInstaller import com.intellij.ide.plugins.PluginManagerCore @@ -16,16 +16,16 @@ import com.intellij.ide.plugins.PluginStateListener import com.intellij.openapi.components.service import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.project.Project -import com.intellij.openapi.startup.StartupActivity +import com.intellij.openapi.startup.ProjectActivity import com.intellij.openapi.vfs.LocalFileSystem import org.slf4j.LoggerFactory import java.util.* -class PostStartupActivity : StartupActivity { +class PostStartupActivity : ProjectActivity { private val logger = LoggerFactory.getLogger(javaClass) - override fun runActivity(project: Project) { + override suspend fun execute(project: Project) { ApplicationServiceUtil.getService(LoggerService::class.java).initializeLogger() val version = PluginManagerCore.getPlugin(PluginId.getId("com.github.bridgecrewio.prismacloud"))?.version logger.info("Starting Prisma Cloud JetBrains plugin version $version") @@ -38,6 +38,12 @@ class PostStartupActivity : StartupActivity { } }) +// ApplicationServiceUtil.getService(CommonsClient::class.java).helloWorld() +// logger.info(ApplicationServiceUtil.getService(CommonsClient::class.java).add(3, 4).toString()) +// val request = Request(listOf("test", "best"), "mest", 1) +// val res = ApplicationServiceUtil.getService(CommonsClient::class.java).handleRequest(request) +// logger.info(res.toString()) + PluginInstaller.addStateListener(object : PluginStateListener { override fun install(ideaPluginDescriptor: IdeaPluginDescriptor) { //todo this event wasn't trigger, need review diff --git a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt index bb2f20a..8788e06 100644 --- a/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt +++ b/src/main/kotlin/com/bridgecrew/analytics/AnalyticsService.kt @@ -5,7 +5,7 @@ import com.bridgecrew.cache.CacheDataAnalytics import com.bridgecrew.scheduler.IntervalRunner import com.bridgecrew.services.scan.FullScanStateService import com.bridgecrew.services.scan.ScanTaskResult -import com.bridgecrew.util.ApplicationServiceUtil +import com.bridgecrew.utils.ApplicationServiceUtil import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project diff --git a/src/main/kotlin/com/bridgecrew/api/PrismaApiClient.kt b/src/main/kotlin/com/bridgecrew/api/PrismaApiClient.kt index 08f17d4..53c7a5f 100644 --- a/src/main/kotlin/com/bridgecrew/api/PrismaApiClient.kt +++ b/src/main/kotlin/com/bridgecrew/api/PrismaApiClient.kt @@ -5,12 +5,10 @@ import com.bridgecrew.listeners.CheckovSettingsListener import com.bridgecrew.settings.DEFAULT_REPORTING_INTERVAL import com.bridgecrew.settings.PLUGIN_NAME import com.bridgecrew.settings.PrismaSettingsState -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.bridgecrew.utils.GlobalMapper import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.Service +import kotlinx.coroutines.CoroutineScope import org.slf4j.LoggerFactory import org.springframework.http.HttpEntity import org.springframework.http.HttpHeaders @@ -31,19 +29,15 @@ data class PrismaConnectionDetails( val secretKey: String ) -val mapper = ObjectMapper().apply { - registerModule(KotlinModule.Builder().build()) - configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - setSerializationInclusion(JsonInclude.Include.NON_NULL) -} + @Service -class PrismaApiClient { +class PrismaApiClient(private val cs: CoroutineScope) { private val logger = LoggerFactory.getLogger(javaClass) private var connection: PrismaConnectionDetails? = null private val client = RestTemplate(listOf( - MappingJackson2HttpMessageConverter(mapper) + MappingJackson2HttpMessageConverter(GlobalMapper.i()) )) init { diff --git a/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt b/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt index 1512c4c..eb44d5e 100644 --- a/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt +++ b/src/main/kotlin/com/bridgecrew/cache/CacheDataAnalytics.kt @@ -2,7 +2,7 @@ package com.bridgecrew.cache import com.bridgecrew.analytics.AnalyticsData -import com.bridgecrew.api.mapper +import com.bridgecrew.utils.GlobalMapper import com.intellij.openapi.project.Project class CacheDataAnalytics(private val project: Project) { @@ -13,14 +13,14 @@ class CacheDataAnalytics(private val project: Project) { return } - val analyticsEventDataCached = data.split("\n").toMutableList().map { mapper.readValue(it, AnalyticsData::class.java) } + val analyticsEventDataCached = data.split("\n").toMutableList().map { GlobalMapper.i().readValue(it, AnalyticsData::class.java) } analyticsEventData.addAll(analyticsEventDataCached) CacheDataAnalyticsStorage(project).clear() } fun stash(analyticsEventData: MutableList) { - val data = analyticsEventData.joinToString("\n") { mapper.writeValueAsString(it) } + val data = analyticsEventData.joinToString("\n") { GlobalMapper.i().writeValueAsString(it) } CacheDataAnalyticsStorage(project).writeDataToFile(data) } } diff --git a/src/main/kotlin/com/bridgecrew/commons/CommonsClient.kt b/src/main/kotlin/com/bridgecrew/commons/CommonsClient.kt new file mode 100644 index 0000000..b5cfce7 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/commons/CommonsClient.kt @@ -0,0 +1,62 @@ +package com.bridgecrew.commons + +import com.bridgecrew.commons.models.Request +import com.bridgecrew.commons.models.Response +import com.bridgecrew.utils.GlobalMapper +import com.fasterxml.jackson.core.JsonProcessingException +import com.intellij.openapi.components.Service +import com.sun.jna.Native +import org.eclipse.sisu.Nullable +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +@Service +class CommonsClient { + + private val logger: Logger = LoggerFactory.getLogger(javaClass) + + @Nullable + private var commons: CommonsLibrary? = null + + init { + try { + val file = Native.extractFromResourcePath( + "/lib/${System.mapLibraryName("commons-${getArch()}")}", + javaClass.classLoader + ) + logger.info("Loading commons lib from ${file.absolutePath}") + commons = Native.load(file.absolutePath, CommonsLibrary::class.java) + logger.info("Successfully loaded commons from ${file.absolutePath}") + } catch (e: Exception) { + logger.error("Failed to load commons lib", e) + } + } + + fun helloWorld() { + commons?.HelloWorld() + } + + fun add(a: Int, b: Int): Int { + return commons?.Add(a, b) ?: 0 + } + + fun handleRequest(request: Request?): Response { + try { + val requestJson = GlobalMapper.i().writeValueAsString(request) + val response = commons?.HandleRequest(requestJson) + return GlobalMapper.i().readValue(response, Response::class.java) + } catch (e: JsonProcessingException) { + logger.error("Failed to handle request", e) + return Response(e.message) + } + } + + @Throws(Exception::class) + private fun getArch(): String { + return when (val arch = System.getProperty("os.arch").lowercase()) { + "x86_64", "amd64" -> "x64" + "arm", "arm64", "aarch64" -> "arm" + else -> throw Exception("Unsupported architecture: $arch") + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/commons/CommonsLibrary.kt b/src/main/kotlin/com/bridgecrew/commons/CommonsLibrary.kt new file mode 100644 index 0000000..4249bc3 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/commons/CommonsLibrary.kt @@ -0,0 +1,12 @@ +package com.bridgecrew.commons + +import com.sun.jna.Library + +interface CommonsLibrary : Library { + + fun HelloWorld() + + fun Add(a: Int, b: Int): Int + + fun HandleRequest(request: String?): String? +} \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/commons/models/PluginCommonsResponse.kt b/src/main/kotlin/com/bridgecrew/commons/models/PluginCommonsResponse.kt new file mode 100644 index 0000000..e4393d7 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/commons/models/PluginCommonsResponse.kt @@ -0,0 +1,6 @@ +package com.bridgecrew.commons.models + +open class PluginCommonsResponse( + + var error: String? +) \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/commons/models/Request.kt b/src/main/kotlin/com/bridgecrew/commons/models/Request.kt new file mode 100644 index 0000000..d737a77 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/commons/models/Request.kt @@ -0,0 +1,7 @@ +package com.bridgecrew.commons.models + +data class Request( + var strings: List, + var anotherString: String, + var number: Int +) \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/commons/models/Response.kt b/src/main/kotlin/com/bridgecrew/commons/models/Response.kt new file mode 100644 index 0000000..032f65b --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/commons/models/Response.kt @@ -0,0 +1,11 @@ +package com.bridgecrew.commons.models + +data class Response( + var strings: List?, + var result: Boolean? +) : PluginCommonsResponse(null) { + + constructor(error: String?) : this(null, null) { + this.error = error + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/scheduler/IntervalRunner.kt b/src/main/kotlin/com/bridgecrew/scheduler/IntervalRunner.kt index eca935c..16a53af 100644 --- a/src/main/kotlin/com/bridgecrew/scheduler/IntervalRunner.kt +++ b/src/main/kotlin/com/bridgecrew/scheduler/IntervalRunner.kt @@ -3,7 +3,6 @@ package com.bridgecrew.scheduler import org.apache.commons.lang3.time.StopWatch import org.slf4j.LoggerFactory import java.util.* -import java.util.concurrent.TimeUnit class IntervalRunner(private val name: String) { @@ -16,13 +15,8 @@ class IntervalRunner(private val name: String) { timer.schedule(object : TimerTask() { override fun run() { try { - stopWatch.time intervalFunction() - logger.info( - "Interval function for $name executed with delay " + TimeUnit.MILLISECONDS.toSeconds( - stopWatch.time - ) - ) + logger.info("Interval function for $name executed with delay " + stopWatch.duration.toSeconds()) } catch (e: Throwable) { logger.info("Catch the exception: $e") stopWatch.stop() diff --git a/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt b/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt index 14eab9c..409f6f7 100644 --- a/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt +++ b/src/main/kotlin/com/bridgecrew/services/scan/FullScanState.kt @@ -1,7 +1,6 @@ package com.bridgecrew.services.scan import com.bridgecrew.analytics.AnalyticsService -import com.bridgecrew.api.mapper import com.bridgecrew.listeners.CheckovScanListener import com.bridgecrew.results.BaseCheckovResult import com.bridgecrew.services.ResultsCacheService @@ -10,6 +9,7 @@ import com.bridgecrew.ui.actions.CheckovScanAction import com.bridgecrew.ui.actions.SeverityFilterActions import com.bridgecrew.utils.DESIRED_NUMBER_OF_FRAMEWORK_FOR_FULL_SCAN import com.bridgecrew.utils.FULL_SCAN_STATE_FILE +import com.bridgecrew.utils.GlobalMapper import com.bridgecrew.utils.createCheckovTempFile import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import com.intellij.notification.NotificationType @@ -82,13 +82,13 @@ class FullScanStateService(val project: Project) { fun saveCurrentState() { val currentResults: List = project.service().getAdjustedCheckovResults() stateFile = createCheckovTempFile(FULL_SCAN_STATE_FILE, ".json") - stateFile!!.writeText(mapper.writeValueAsString(currentResults)) + stateFile!!.writeText(GlobalMapper.i().writeValueAsString(currentResults)) } private fun returnToPreviousState() { try { val stateContent = stateFile!!.readText() - val checkovResultsList: MutableList = mapper.readValue(stateContent, jacksonTypeRef()) + val checkovResultsList: MutableList = GlobalMapper.i().readValue(stateContent, jacksonTypeRef()) project.service().checkovResults = checkovResultsList SeverityFilterActions.restartState() } catch (e: Exception) { diff --git a/src/main/kotlin/com/bridgecrew/ui/CheckovToolWindowDescriptionPanel.kt b/src/main/kotlin/com/bridgecrew/ui/CheckovToolWindowDescriptionPanel.kt index a9a41e0..60889ea 100644 --- a/src/main/kotlin/com/bridgecrew/ui/CheckovToolWindowDescriptionPanel.kt +++ b/src/main/kotlin/com/bridgecrew/ui/CheckovToolWindowDescriptionPanel.kt @@ -146,7 +146,7 @@ class CheckovToolWindowDescriptionPanel(val project: Project) : SimpleToolWindow scanButton.addActionListener { val scanAction = ActionManager.getInstance().getAction("com.bridgecrew.ui.actions.CheckovScanAction") val dataContext = DataManager.getInstance().getDataContext(scanButton) - val action = AnActionEvent.createFromDataContext(ActionPlaces.UNKNOWN, null, dataContext) + val action = AnActionEvent.createFromDataContext(ActionPlaces.TOOLWINDOW_CONTENT, null, dataContext) action.presentation.icon = AllIcons.Actions.Execute scanAction.actionPerformed(action) } diff --git a/src/main/kotlin/com/bridgecrew/ui/PrismaSettingsComponent.kt b/src/main/kotlin/com/bridgecrew/ui/PrismaSettingsComponent.kt index 6aadfe3..d0007d8 100644 --- a/src/main/kotlin/com/bridgecrew/ui/PrismaSettingsComponent.kt +++ b/src/main/kotlin/com/bridgecrew/ui/PrismaSettingsComponent.kt @@ -10,7 +10,7 @@ import com.intellij.util.ui.JBUI import java.awt.Dimension import java.awt.GridBagConstraints import java.awt.GridBagLayout -import java.net.URL +import java.net.URI import java.text.NumberFormat import java.util.* import javax.swing.* @@ -136,7 +136,7 @@ class PrismaSettingsComponent(private val configurable: Configurable) { fun isValid(): Boolean { try { - val url = URL(prismaURLField.text) + val url = URI(prismaURLField.text).toURL() if (url.protocol.equals("http", ignoreCase = true)) { validationResults.text = "Prisma URL protocol must be https" return false diff --git a/src/main/kotlin/com/bridgecrew/ui/actions/CheckovScanAction.kt b/src/main/kotlin/com/bridgecrew/ui/actions/CheckovScanAction.kt index 292016d..a1af4fc 100644 --- a/src/main/kotlin/com/bridgecrew/ui/actions/CheckovScanAction.kt +++ b/src/main/kotlin/com/bridgecrew/ui/actions/CheckovScanAction.kt @@ -3,9 +3,11 @@ package com.bridgecrew.ui.actions import com.bridgecrew.analytics.AnalyticsService import com.bridgecrew.services.scan.CheckovScanService import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.Presentation +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.project.DumbAware @@ -19,21 +21,24 @@ object CheckovScanAction : AnAction(), DumbAware { presentation.isEnabled = false } -// TODO: Uncomment when moving to Kotlin 2 + Java 21 -// override fun getActionUpdateThread(): ActionUpdateThread { -// return ActionUpdateThread.EDT -// } + override fun getActionUpdateThread(): ActionUpdateThread { + return ActionUpdateThread.EDT + } override fun actionPerformed(actionEvent: AnActionEvent) { val project = actionEvent.project if (actionEvent.presentation.icon == AllIcons.Actions.Execute) { isExecuteState = false - project!!.service().fullScanButtonWasPressed() - project.service().scanProject(project) + ApplicationManager.getApplication().invokeLater { + project!!.service().fullScanButtonWasPressed() + project.service().scanProject(project) + } } else { isExecuteState = true presentation.isEnabled = false - project?.service()?.cancelFullScan(project) + ApplicationManager.getApplication().invokeLater { + project?.service()?.cancelFullScan(project) + } } updateIcon() } diff --git a/src/main/kotlin/com/bridgecrew/ui/actions/ShowLogFileAction.kt b/src/main/kotlin/com/bridgecrew/ui/actions/ShowLogFileAction.kt index 3960caa..3f99407 100644 --- a/src/main/kotlin/com/bridgecrew/ui/actions/ShowLogFileAction.kt +++ b/src/main/kotlin/com/bridgecrew/ui/actions/ShowLogFileAction.kt @@ -2,54 +2,28 @@ package com.bridgecrew.ui.actions import com.bridgecrew.icons.CheckovIcons import com.bridgecrew.log.LoggerService -import com.bridgecrew.util.ApplicationServiceUtil +import com.bridgecrew.utils.ApplicationServiceUtil +import com.intellij.ide.actions.RevealFileAction +import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.project.DumbAware -import org.slf4j.LoggerFactory -import java.awt.Desktop import java.io.File -import java.io.IOException class ShowLogFileAction : AnAction(), DumbAware { - private val logger = LoggerFactory.getLogger(this::class.java) - override fun update(event: AnActionEvent) { val presentation: Presentation = event.presentation presentation.icon = CheckovIcons.showLogsIcon } -// TODO: Uncomment when moving to Kotlin 2 + Java 21 -// override fun getActionUpdateThread(): ActionUpdateThread { -// return ActionUpdateThread.EDT -// } + override fun getActionUpdateThread(): ActionUpdateThread { + return ActionUpdateThread.EDT + } override fun actionPerformed(event: AnActionEvent) { val logFilePath = ApplicationServiceUtil.getService(LoggerService::class.java).getLogFilePath() - val file = File(logFilePath) - - if (!file.exists()) { - logger.error("File does not exist: $logFilePath") - return - } - - if (!Desktop.isDesktopSupported()) { - logger.error("Desktop is not supported on this platform.") - return - } - - val desktop = Desktop.getDesktop() - if (!desktop.isSupported(Desktop.Action.OPEN)) { - logger.error("Open action is not supported on this platform.") - return - } - - try { - desktop.open(file) - } catch (e: IOException) { - logger.error("An error occurred while trying to open the file: ${e.message}", e) - } + RevealFileAction.openFile(File(logFilePath)) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/ui/components/ActionLink.kt b/src/main/kotlin/com/bridgecrew/ui/components/ActionLink.kt index 9370520..6475c73 100644 --- a/src/main/kotlin/com/bridgecrew/ui/components/ActionLink.kt +++ b/src/main/kotlin/com/bridgecrew/ui/components/ActionLink.kt @@ -1,8 +1,10 @@ package com.bridgecrew.ui.components -import com.intellij.openapi.application.ApplicationManager import com.intellij.ui.AnimatedIcon +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Runnable +import kotlinx.coroutines.launch import java.awt.Cursor import java.awt.event.MouseAdapter import java.awt.event.MouseEvent @@ -28,7 +30,7 @@ class ActionLink( setDefaultState() return } - ApplicationManager.getApplication().invokeLater { + CoroutineScope(Dispatchers.IO).launch { onClick.run() setDefaultState() } diff --git a/src/main/kotlin/com/bridgecrew/utils/ApplicationServiceUtil.kt b/src/main/kotlin/com/bridgecrew/utils/ApplicationServiceUtil.kt new file mode 100644 index 0000000..c67e123 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/utils/ApplicationServiceUtil.kt @@ -0,0 +1,24 @@ +package com.bridgecrew.utils + +import com.intellij.openapi.application.ApplicationManager +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +class ApplicationServiceUtil { + + companion object { + + val logger: Logger = LoggerFactory.getLogger(ApplicationServiceUtil::class.java) + + @JvmStatic + fun getService(clazz: Class): T { + val service = ApplicationManager.getApplication().getService(clazz) + if (service == null) { + val message = String.format("Could not find service %s", clazz.simpleName) + logger.error(message) + throw IllegalArgumentException(message) + } + return service + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/utils/CheckovUtils.kt b/src/main/kotlin/com/bridgecrew/utils/CheckovUtils.kt index ef093c6..1da5570 100644 --- a/src/main/kotlin/com/bridgecrew/utils/CheckovUtils.kt +++ b/src/main/kotlin/com/bridgecrew/utils/CheckovUtils.kt @@ -2,7 +2,6 @@ package com.bridgecrew.utils import com.bridgecrew.CheckovResult import com.bridgecrew.VulnerabilityDetails -import com.bridgecrew.api.mapper import com.bridgecrew.results.BaseCheckovResult import com.bridgecrew.results.Category import com.bridgecrew.results.CheckType @@ -141,7 +140,7 @@ class CheckovUtils { val failedChecks = results.getJSONArray("failed_checks") val checkType = outputObj.getString("check_type") - val checkovResults: ArrayList = mapper.readValue(failedChecks.toString(), jacksonTypeRef()) + val checkovResults: ArrayList = GlobalMapper.i().readValue(failedChecks.toString(), jacksonTypeRef()) checkovResults.forEach { result -> result.check_type = checkType } return checkovResults diff --git a/src/main/kotlin/com/bridgecrew/utils/GlobalMapper.kt b/src/main/kotlin/com/bridgecrew/utils/GlobalMapper.kt new file mode 100644 index 0000000..76b6ec5 --- /dev/null +++ b/src/main/kotlin/com/bridgecrew/utils/GlobalMapper.kt @@ -0,0 +1,23 @@ +package com.bridgecrew.utils + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule + +class GlobalMapper { + + companion object { + + private val mapper: ObjectMapper = ObjectMapper().apply { + registerModule(KotlinModule.Builder().build()); + configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + @JvmStatic + fun i(): ObjectMapper { + return mapper + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bridgecrew/utils/fileUtils.kt b/src/main/kotlin/com/bridgecrew/utils/fileUtils.kt index 57639be..3d5bfd5 100644 --- a/src/main/kotlin/com/bridgecrew/utils/fileUtils.kt +++ b/src/main/kotlin/com/bridgecrew/utils/fileUtils.kt @@ -10,7 +10,7 @@ import org.apache.commons.io.FilenameUtils import org.slf4j.Logger import org.slf4j.LoggerFactory import java.io.File -import java.net.URL +import java.net.URI import java.nio.file.Files import java.nio.file.Path @@ -60,7 +60,7 @@ fun isUrl(url: String?): Boolean { return false } return try { - URL(url) + URI(url).toURL() true } catch (e: Throwable) { false diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 50e4f6f..3711c2f 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -11,7 +11,6 @@ com.intellij.modules.lang com.intellij.modules.platform -