diff --git a/.changes/next-release/bugfix-dbdc4495-49ce-4635-939b-9e6f50c105eb.json b/.changes/next-release/bugfix-dbdc4495-49ce-4635-939b-9e6f50c105eb.json new file mode 100644 index 0000000000..cb04be7fdd --- /dev/null +++ b/.changes/next-release/bugfix-dbdc4495-49ce-4635-939b-9e6f50c105eb.json @@ -0,0 +1,4 @@ +{ + "type" : "bugfix", + "description" : "Security Scan: Improved error notifications" +} \ No newline at end of file diff --git a/plugins/toolkit/jetbrains-core/it/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererCodeScanIntegrationTest.kt b/plugins/toolkit/jetbrains-core/it/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererCodeScanIntegrationTest.kt index 07e3ca6c2c..7a0c2f0219 100644 --- a/plugins/toolkit/jetbrains-core/it/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererCodeScanIntegrationTest.kt +++ b/plugins/toolkit/jetbrains-core/it/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererCodeScanIntegrationTest.kt @@ -8,8 +8,6 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.Test import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.cppFileName import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.cppTestLeftContext -import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.sessionconfig.CodeScanSessionConfig -import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials import software.aws.toolkits.resources.message @@ -58,14 +56,7 @@ class CodeWhispererCodeScanIntegrationTest : CodeWhispererIntegrationTestBase() projectRule.fixture.openFileInEditor(file.virtualFile) } testCodeScanWithErrorMessage( - message( - "codewhisperer.codescan.file_too_large", - CodeScanSessionConfig.create( - file.virtualFile, - projectRule.project, - CodeWhispererConstants.CodeAnalysisScope.PROJECT - ).getPresentablePayloadLimit() - ) + message("codewhisperer.codescan.file_too_large") ) } diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanException.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanException.kt index 398c0bd612..d2a7c21a4d 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanException.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanException.kt @@ -7,11 +7,13 @@ import software.aws.toolkits.resources.message open class CodeWhispererCodeScanException(override val message: String?) : RuntimeException() +open class UploadCodeScanException(override val message: String?) : Exception() + internal fun noFileOpenError(): Nothing = throw CodeWhispererCodeScanException(message("codewhisperer.codescan.no_file_open")) -internal fun codeScanFailed(): Nothing = - throw CodeWhispererCodeScanException(message("codewhisperer.codescan.service_error")) +internal fun codeScanFailed(errorMessage: String): Nothing = + throw Exception(errorMessage) internal fun cannotFindFile(file: String?): Nothing = error(message("codewhisperer.codescan.file_not_found", file ?: "")) @@ -22,11 +24,14 @@ internal fun cannotFindBuildArtifacts(): Nothing = internal fun fileFormatNotSupported(format: String): Nothing = throw CodeWhispererCodeScanException(message("codewhisperer.codescan.file_ext_not_supported", format)) -internal fun fileTooLarge(presentableSize: String): Nothing = - throw CodeWhispererCodeScanException(message("codewhisperer.codescan.file_too_large", presentableSize)) +internal fun fileTooLarge(): Nothing = + throw CodeWhispererCodeScanException(message("codewhisperer.codescan.file_too_large")) + +internal fun uploadArtifactFailedError(errorMessage: String): Nothing = + throw UploadCodeScanException(errorMessage) -internal fun uploadArtifactFailedError(): Nothing = - throw CodeWhispererCodeScanException(message("codewhisperer.codescan.upload_to_s3_failed")) +internal fun invalidSourceZipError(): Nothing = + throw CodeWhispererCodeScanException(message("codewhisperer.codescan.invalid_source_zip_telemetry")) internal fun noSupportedFilesError(): Nothing = throw CodeWhispererCodeScanException(message("codewhisperer.codescan.unsupported_language_error")) diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanManager.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanManager.kt index 4326e47569..e6d49e53ae 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanManager.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanManager.kt @@ -305,7 +305,7 @@ class CodeWhispererCodeScanManager(val project: Project) { if (e.cause?.message?.contains("com.intellij.openapi.compiler.CompilerPaths") == true) { message("codewhisperer.codescan.java_module_not_found") } else { - message("codewhisperer.codescan.service_error") + null } } else -> null @@ -324,10 +324,14 @@ class CodeWhispererCodeScanManager(val project: Project) { fun handleException(coroutineContext: CoroutineContext, e: Exception, scope: CodeWhispererConstants.CodeAnalysisScope): String { val errorMessage = when (e) { - is CodeWhispererException -> e.awsErrorDetails().errorMessage() ?: message("codewhisperer.codescan.service_error") - is CodeWhispererCodeScanException -> e.message + is CodeWhispererException -> e.awsErrorDetails().errorMessage() ?: message("codewhisperer.codescan.run_scan_error") + is CodeWhispererCodeScanException -> when (e.message) { + message("codewhisperer.codescan.invalid_source_zip_telemetry") -> message("codewhisperer.codescan.run_scan_error") + else -> e.message + } + is UploadCodeScanException -> message("codewhisperer.codescan.upload_to_s3_failed") is WaiterTimeoutException, is TimeoutCancellationException -> message("codewhisperer.codescan.scan_timed_out") - is CancellationException -> "Code scan job cancelled by user." + is CancellationException -> message("codewhisperer.codescan.cancelled_by_user_exception") else -> null } ?: message("codewhisperer.codescan.run_scan_error") @@ -358,7 +362,22 @@ class CodeWhispererCodeScanManager(val project: Project) { "stacktrace: ${e.stackTrace.contentDeepToString()}" } } - return errorMessage + + val telemetryErrorMessage = when (e) { + is CodeWhispererException -> e.awsErrorDetails().errorMessage() ?: message("codewhisperer.codescan.run_scan_error_telemetry") + is CodeWhispererCodeScanException -> when (e.message) { + message("codewhisperer.codescan.no_file_open") -> message("codewhisperer.codescan.no_file_open_telemetry") + message("codewhisperer.codescan.unsupported_language_error") -> message("codewhisperer.codescan.unsupported_language_error_telemetry") + message("codewhisperer.codescan.file_too_large") -> message("codewhisperer.codescan.file_too_large_telemetry") + else -> e.message + } + is UploadCodeScanException -> e.message + is WaiterTimeoutException, is TimeoutCancellationException -> message("codewhisperer.codescan.scan_timed_out") + is CancellationException -> message("codewhisperer.codescan.cancelled_by_user_exception") + else -> e.message + } ?: message("codewhisperer.codescan.run_scan_error_telemetry") + + return telemetryErrorMessage } /** diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt index 72f6a785c5..180bf3f6ea 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt @@ -57,6 +57,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhisperer import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.TOTAL_MILLIS_IN_SECOND import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.notifyErrorCodeWhispererUsageLimit import software.aws.toolkits.jetbrains.utils.assertIsNonDispatchThread +import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.CodewhispererLanguage import java.io.File import java.io.FileInputStream @@ -152,7 +153,8 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) { "Status: ${createCodeScanResponse.status()} for request id: ${createCodeScanResponse.responseMetadata().requestId()}" } } - codeScanFailed() + val errorMessage = createCodeScanResponse.errorMessage()?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry") + codeScanFailed(errorMessage) } val jobId = createCodeScanResponse.jobId() codeScanResponseContext = codeScanResponseContext.copy(codeScanJobId = jobId) @@ -188,7 +190,8 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) { "Status: ${getCodeScanResponse.status()} for request id: ${getCodeScanResponse.responseMetadata().requestId()}" } } - codeScanFailed() + val errorMessage = getCodeScanResponse.errorMessage()?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry") + codeScanFailed(errorMessage) } } @@ -250,7 +253,11 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) { /** * Creates an upload URL and uplaods the zip file to the presigned URL */ - fun createUploadUrlAndUpload(zipFile: File, artifactType: String, codeScanName: String): CreateUploadUrlResponse = try { + fun createUploadUrlAndUpload(zipFile: File, artifactType: String, codeScanName: String): CreateUploadUrlResponse { + // Throw error if zipFile is invalid. + if (!zipFile.exists()) { + invalidSourceZipError() + } val fileMd5: String = Base64.getEncoder().encodeToString(DigestUtils.md5(FileInputStream(zipFile))) val createUploadUrlResponse = createUploadUrl(fileMd5, artifactType, codeScanName) val url = createUploadUrlResponse.uploadUrl() @@ -265,20 +272,21 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) { createUploadUrlResponse.kmsKeyArn(), createUploadUrlResponse.requestHeaders() ) - createUploadUrlResponse - } catch (e: Exception) { - LOG.error { "Security scan failed. Something went wrong uploading artifacts: ${e.message}" } - uploadArtifactFailedError() + return createUploadUrlResponse } - fun createUploadUrl(md5Content: String, artifactType: String, codeScanName: String): CreateUploadUrlResponse = clientAdaptor.createUploadUrl( - CreateUploadUrlRequest.builder() - .contentMd5(md5Content) - .artifactType(artifactType) - .uploadIntent(getUploadIntent(sessionContext.codeAnalysisScope)) - .uploadContext(UploadContext.fromCodeAnalysisUploadContext(CodeAnalysisUploadContext.builder().codeScanName(codeScanName).build())) - .build() - ) + fun createUploadUrl(md5Content: String, artifactType: String, codeScanName: String): CreateUploadUrlResponse = try { + clientAdaptor.createUploadUrl( + CreateUploadUrlRequest.builder() + .contentMd5(md5Content) + .artifactType(artifactType) + .uploadIntent(getUploadIntent(sessionContext.codeAnalysisScope)) + .uploadContext(UploadContext.fromCodeAnalysisUploadContext(CodeAnalysisUploadContext.builder().codeScanName(codeScanName).build())) + .build() + ) + } catch (e: Exception) { + throw e + } private fun getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope): UploadIntent = when (scope) { CodeWhispererConstants.CodeAnalysisScope.FILE -> UploadIntent.AUTOMATIC_FILE_SECURITY_SCAN @@ -287,25 +295,30 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) { @Throws(IOException::class) fun uploadArtifactToS3(url: String, uploadId: String, fileToUpload: File, md5: String, kmsArn: String?, requestHeaders: Map?) { - val uploadIdJson = """{"uploadId":"$uploadId"}""" - HttpRequests.put(url, "application/zip").userAgent(AwsClientManager.getUserAgent()).tuner { - if (requestHeaders.isNullOrEmpty()) { - it.setRequestProperty(CONTENT_MD5, md5) - it.setRequestProperty(CONTENT_TYPE, APPLICATION_ZIP) - it.setRequestProperty(SERVER_SIDE_ENCRYPTION, AWS_KMS) - if (kmsArn?.isNotEmpty() == true) { - it.setRequestProperty(SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID, kmsArn) - } - it.setRequestProperty(SERVER_SIDE_ENCRYPTION_CONTEXT, Base64.getEncoder().encodeToString(uploadIdJson.toByteArray())) - } else { - requestHeaders.forEach { entry -> - it.setRequestProperty(entry.key, entry.value) + try { + val uploadIdJson = """{"uploadId":"$uploadId"}""" + HttpRequests.put(url, "application/zip").userAgent(AwsClientManager.getUserAgent()).tuner { + if (requestHeaders.isNullOrEmpty()) { + it.setRequestProperty(CONTENT_MD5, md5) + it.setRequestProperty(CONTENT_TYPE, APPLICATION_ZIP) + it.setRequestProperty(SERVER_SIDE_ENCRYPTION, AWS_KMS) + if (kmsArn?.isNotEmpty() == true) { + it.setRequestProperty(SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID, kmsArn) + } + it.setRequestProperty(SERVER_SIDE_ENCRYPTION_CONTEXT, Base64.getEncoder().encodeToString(uploadIdJson.toByteArray())) + } else { + requestHeaders.forEach { entry -> + it.setRequestProperty(entry.key, entry.value) + } } + }.connect { + val connection = it.connection as HttpURLConnection + connection.setFixedLengthStreamingMode(fileToUpload.length()) + IoUtils.copy(fileToUpload.inputStream(), connection.outputStream) } - }.connect { - val connection = it.connection as HttpURLConnection - connection.setFixedLengthStreamingMode(fileToUpload.length()) - IoUtils.copy(fileToUpload.inputStream(), connection.outputStream) + } catch (e: Exception) { + val errorMessage = e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry") + throw uploadArtifactFailedError(errorMessage) } } diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/sessionconfig/CodeScanSessionConfig.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/sessionconfig/CodeScanSessionConfig.kt index 182b555534..3a4ddea798 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/sessionconfig/CodeScanSessionConfig.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/sessionconfig/CodeScanSessionConfig.kt @@ -31,8 +31,6 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhisperer import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.DEFAULT_PAYLOAD_LIMIT_IN_BYTES import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.FILE_SCAN_PAYLOAD_SIZE_LIMIT_IN_BYTES import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.FILE_SCAN_TIMEOUT_IN_SECONDS -import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.TOTAL_BYTES_IN_KB -import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.TOTAL_BYTES_IN_MB import software.aws.toolkits.telemetry.CodewhispererLanguage import java.io.File import java.nio.file.Files @@ -87,7 +85,7 @@ class CodeScanSessionConfig( // Fail fast if the selected file size is greater than the payload limit. if (selectedFile != null && selectedFile.length > getPayloadLimitInBytes()) { - fileTooLarge(getPresentablePayloadLimit()) + fileTooLarge() } val start = Instant.now().toEpochMilli() @@ -131,11 +129,6 @@ class CodeScanSessionConfig( */ fun createPayloadTimeoutInSeconds(): Long = CODE_SCAN_CREATE_PAYLOAD_TIMEOUT_IN_SECONDS - fun getPresentablePayloadLimit(): String = when (getPayloadLimitInBytes() >= TOTAL_BYTES_IN_MB) { - true -> "${getPayloadLimitInBytes() / TOTAL_BYTES_IN_MB}MB" - false -> "${getPayloadLimitInBytes() / TOTAL_BYTES_IN_KB}KB" - } - private fun countLinesInVirtualFile(virtualFile: VirtualFile): Int { val bufferedReader = virtualFile.inputStream.bufferedReader() return bufferedReader.useLines { lines -> lines.count() } diff --git a/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeFileScanTest.kt b/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeFileScanTest.kt index 66b48b2b5a..d0430abbb3 100644 --- a/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeFileScanTest.kt +++ b/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeFileScanTest.kt @@ -274,21 +274,21 @@ class CodeWhispererCodeFileScanTest : CodeWhispererCodeScanTestBase(PythonCodeIn val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } @Test fun `test run() - createCodeScan error`() { mockClient.stub { - onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererException::class.java) + onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanException::class.java) } runBlocking { val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } @@ -302,7 +302,7 @@ class CodeWhispererCodeFileScanTest : CodeWhispererCodeScanTestBase(PythonCodeIn val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } diff --git a/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt b/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt index eaeaa81d0a..67968b52e4 100644 --- a/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt +++ b/plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt @@ -10,6 +10,7 @@ import org.apache.commons.codec.digest.DigestUtils import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test +import org.junit.jupiter.api.assertThrows import org.mockito.ArgumentMatchers.anyString import org.mockito.internal.verification.Times import org.mockito.kotlin.any @@ -112,6 +113,15 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh ) } + @Test + fun `test createUploadUrlAndUpload() with invalid source zip file`() { + val invalidZipFile = File("/path/file.zip") + + assertThrows { + codeScanSessionSpy.createUploadUrlAndUpload(invalidZipFile, "artifactType", codeScanName) + } + } + @Test fun `test createUploadUrl()`() { val response = codeScanSessionSpy.createUploadUrl("md5", "type", codeScanName) @@ -205,21 +215,21 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } @Test fun `test run() - createCodeScan error`() { mockClient.stub { - onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererException::class.java) + onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanException::class.java) } runBlocking { val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } @@ -233,7 +243,7 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh val codeScanResponse = codeScanSessionSpy.run() assertThat(codeScanResponse).isInstanceOf() assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext) - assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() + assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf() } } diff --git a/plugins/toolkit/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/toolkit/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index c5a3dbc3d0..0ea04473df 100644 --- a/plugins/toolkit/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/toolkit/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -731,6 +731,7 @@ codewhisperer.actions.view_documentation.title=View Documentation codewhisperer.codescan.apply_fix_button_label=Apply fix codewhisperer.codescan.apply_fix_button_tooltip=Apply suggested fix codewhisperer.codescan.build_artifacts_not_found=Cannot find build artifacts for the project. Try rebuilding the Java project in IDE or specify compilation output path in File | Project Structure... | Project | Compiler output: +codewhisperer.codescan.cancelled_by_user_exception=Code scan job cancelled by user. codewhisperer.codescan.cannot_read_file=Error while reading file {0} codewhisperer.codescan.cwe_label=Common Weakness Enumeration (CWE) codewhisperer.codescan.detector_library_label=Detector library @@ -738,16 +739,20 @@ codewhisperer.codescan.explain_button_label=Amazon Q: Explain codewhisperer.codescan.file_ext_not_supported=File extension {0} is not supported for Amazon Q Security Scan feature. Please try again with a valid file format - java, python, javascript, typescript, csharp, yaml, json, tf, hcl, ruby, go. codewhisperer.codescan.file_name_issues_count= {0} {1} {2, choice, 1#1 issue|2#{2,number} issues} codewhisperer.codescan.file_not_found=Cannot find file {0} -codewhisperer.codescan.file_too_large=Selected file is larger than {0}. Please try again with a different file. +codewhisperer.codescan.file_too_large=Amazon Q: The selected file exceeds the input artifact limit. Try again with a smaller file. For more information about scan limits, see the Amazon Q documentation. +codewhisperer.codescan.file_too_large_telemetry=Payload size limit reached. codewhisperer.codescan.fix_applied_fail=Apply fix command failed. {0} codewhisperer.codescan.fix_available_label=Code fix available codewhisperer.codescan.fix_button_label=Fix with Q +codewhisperer.codescan.invalid_source_zip_telemetry=Failed to create valid source zip. codewhisperer.codescan.java_module_not_found=Java plugin is required for scanning Java files, install Java plugin or perform the code scan in Intellij Idea instead. -codewhisperer.codescan.no_file_open=No file is open in an active editor. Please open a file in the editor to start the Security Scan. +codewhisperer.codescan.no_file_open=Amazon Q: No file is open in an active editor. Open a file to start a Security Scan. +codewhisperer.codescan.no_file_open_telemetry=Open a valid file to scan. codewhisperer.codescan.problems_window_not_found=Unable to display Security Scan results as the Problems View tool window cannot be fetched. codewhisperer.codescan.run_scan=Run Project Scan codewhisperer.codescan.run_scan_complete= Security Scan completed for {0, choice, 1#1 file|2#{0,number} files}. {1, choice, 0#No issues|1#1 issue|2#{1,number} issues} found in {2}. {3, choice, 0# |1# File size limit reached.} Last Run {5} -codewhisperer.codescan.run_scan_error=We encountered an error while scanning for security issues. Please try again. +codewhisperer.codescan.run_scan_error=Amazon Q encountered an error while scanning for security issues. Please try again later. +codewhisperer.codescan.run_scan_error_telemetry=Security scan failed. codewhisperer.codescan.run_scan_info=Select 'Run' in toolbar to scan this package for security issues. codewhisperer.codescan.scan_display=Amazon Q Security Issues codewhisperer.codescan.scan_display_with_issues=Amazon Q Security Issues {0} @@ -757,15 +762,15 @@ codewhisperer.codescan.scan_recommendation_invalid= {0} {0} files were scanned during the last security scan. -codewhisperer.codescan.service_error=Security Scan failed. Amazon Q error encountered. Please try again. codewhisperer.codescan.stop_scan=Stop Security Scan codewhisperer.codescan.stop_scan_confirm_button=Stop scan codewhisperer.codescan.stop_scan_confirm_message=Are you sure you want to stop ongoing security scan? This scan will be counted as one complete scan towards your monthly security scan limits. codewhisperer.codescan.stopping_scan=Stopping Security Scan... codewhisperer.codescan.suggested_fix_description=Why are we recommending this? codewhisperer.codescan.suggested_fix_label=Suggested code fix preview -codewhisperer.codescan.unsupported_language_error=Project does not contain valid files to scan -codewhisperer.codescan.upload_to_s3_failed=Amazon Q is unable to upload workspace artifacts to Amazon S3 for security scans. For more information, see the Amazon Q documentation or contact your network or organization administrator.
https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/security_iam_manage-access-with-policies.html +codewhisperer.codescan.unsupported_language_error=Amazon Q: Project does not contain valid files to scan +codewhisperer.codescan.unsupported_language_error_telemetry=Project does not contain valid files to scan +codewhisperer.codescan.upload_to_s3_failed=Amazon Q is unable to upload your workspace artifacts to Amazon S3 for security scans. For more information, see the Amazon Q documentation. codewhisperer.codescan.view_scanned_files=View {0} scanned files codewhisperer.credential.login.dialog.exception.cancel_login=Login cancelled codewhisperer.credential.login.dialog.ok_button=Connect @@ -832,7 +837,7 @@ codewhisperer.notification.custom.simple.button.select_another_customization=Sel codewhisperer.notification.custom.simple.button.select_customization=Select customization codewhisperer.notification.remote.ide_unsupported.message=Please update your IDE backend to a 2023.3 or later version to continue using Amazon Q inline suggestions. codewhisperer.notification.remote.ide_unsupported.title=Amazon Q inline suggestion not supported in this IDE version -codewhisperer.notification.usage_limit.codescan.warn.content=Maximum project scan count reached for this month. +codewhisperer.notification.usage_limit.codescan.warn.content=Amazon Q: You have reached the monthly limit for project scans. codewhisperer.notification.usage_limit.codesuggestion.warn.content=You have reached the monthly fair use limit of code recommendations. codewhisperer.popup.button.accept=
 Insert Code 
\u21E5
codewhisperer.popup.button.next=
Next