diff --git a/README.md b/README.md index 88cbf29..13b40a9 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,16 @@ This plugin internally applies the [CycloneDX Gradle plugin](https://github.com/ The plugin offers several tasks: -- `runDepTrackWorkflow`: Runs `generateSbom`, `uploadSbom`, `generateVex`, `uploadVex` and `riskScore` tasks for CI/CD. - `createProject`: Creates a Project - `generateSbom`: Generates the SBOM (Runs "cyclonedxBom" from [cyclonedx-gradle-plugin](https://github.com/CycloneDX/cyclonedx-gradle-plugin) under the hood) - `uploadSbom`: Uploads SBOM file. - `generateVex`: Generates VEX file. - `uploadVex`: Uploads VEX file. +- `analyzeProject`: Triggers Vulnerability Analysis on a specific project +- `riskScore`: Gets risk score. If the risk score is higher than the specified value, the task will fail. - `getOutdatedDependencies`: Gets outdated dependencies. - `getSuppressedVuln`: Gets suppressed vulnerabilities. -- `riskScore`: Gets risk score. If the risk score is higher than the specified value, the task will fail. +- `runDepTrackWorkflow`: Runs `generateSbom`, `uploadSbom`, `generateVex` and `uploadVex` tasks for CI/CD. ### Task Configuration @@ -72,6 +73,14 @@ Each task requires certain inputs which are to be specified in your `build.gradl - `timeout`: *Optional* - If specified, the task will wait for the risk score to be calculated. Default: 0 seconds - `maxRiskScore`: *Optional* - If specified, the task will fail if the risk score is higher than the specified value. +#### analyzeProject + +- `url`: Dependency Track API URL +- `apiKey`: Dependency Track API KEY +- `projectUUID`: *Optional* - You need to set UUID or projectName and projectVersion +- `projectName`: *Optional* - You need to set UUID or projectName and projectVersion +- `projectVersion`: *Optional* - You need to set UUID or projectName and projectVersion + #### getOutdatedDependencies - `url`: Dependency Track API URL diff --git a/src/main/kotlin/com/liftric/dtcp/DepTrackCompanionPlugin.kt b/src/main/kotlin/com/liftric/dtcp/DepTrackCompanionPlugin.kt index 0602378..90c0079 100644 --- a/src/main/kotlin/com/liftric/dtcp/DepTrackCompanionPlugin.kt +++ b/src/main/kotlin/com/liftric/dtcp/DepTrackCompanionPlugin.kt @@ -81,6 +81,16 @@ class DepTrackCompanionPlugin : Plugin { task.dependsOn(generateVex) } + val analyzeProject = project.tasks.register("analyzeProject", AnalyzeProjectTask::class.java) { task -> + task.group = taskGroup + task.description = "Triggers Vulnerability Analysis on a specific project\n" + task.apiKey.set(extension.apiKey) + task.url.set(extension.url) + task.projectUUID.set(extension.projectUUID) + task.projectName.set(extension.projectName) + task.projectVersion.set(extension.projectVersion) + } + val riskScore = project.tasks.register("riskScore", RiskScoreTask::class.java) { task -> task.group = taskGroup task.description = "Get Risk Score" @@ -90,14 +100,13 @@ class DepTrackCompanionPlugin : Plugin { task.projectName.set(extension.projectName) task.projectVersion.set(extension.projectVersion) task.riskScore.set(extension.riskScoreData) - task.mustRunAfter(uploadVex) } project.tasks.register("runDepTrackWorkflow") { task -> task.group = taskGroup task.description = - "Runs uploadSbom, generateVex and uploadVex for CI/CD" - task.dependsOn(generateSbom, uploadSbom, generateVex, uploadVex, riskScore) + "Runs generateSbom, uploadSbom, generateVex, uploadVex for CI/CD integration" + task.dependsOn(generateSbom, uploadSbom, generateVex, uploadVex) } project.tasks.register("getOutdatedDependencies", GetOutdatedDependenciesTask::class.java) { task -> diff --git a/src/main/kotlin/com/liftric/dtcp/tasks/AnalyzeProjectTask.kt b/src/main/kotlin/com/liftric/dtcp/tasks/AnalyzeProjectTask.kt new file mode 100644 index 0000000..a00f36a --- /dev/null +++ b/src/main/kotlin/com/liftric/dtcp/tasks/AnalyzeProjectTask.kt @@ -0,0 +1,53 @@ +package com.liftric.dtcp.tasks + +import com.liftric.dtcp.service.DependencyTrack +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.provider.Property +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +abstract class AnalyzeProjectTask : DefaultTask() { + @get:Input + abstract val apiKey: Property + + @get:Input + abstract val url: Property + + @get:Input + @get:Optional + abstract val projectUUID: Property + + @get:Input + @get:Optional + abstract val projectName: Property + + @get:Input + @get:Optional + abstract val projectVersion: Property + + @TaskAction + fun analyzeProjectTask() { + val apiKeyValue = apiKey.get() + val urlValue = url.get() + + val projectUUIDValue = projectUUID.orNull + val projectNameValue = projectName.orNull + val projectVersionValue = projectVersion.orNull + + val dt = DependencyTrack(apiKeyValue, urlValue) + + val uuid = when { + projectUUIDValue != null -> projectUUIDValue + projectNameValue != null && projectVersionValue != null -> dt.getProject( + projectNameValue, + projectVersionValue + ).uuid + + else -> throw GradleException("Either projectUUID or projectName and projectVersion must be set") + } + + dt.analyzeProjectFindings(uuid) + } +} diff --git a/src/main/kotlin/com/liftric/dtcp/tasks/RiskScoreTask.kt b/src/main/kotlin/com/liftric/dtcp/tasks/RiskScoreTask.kt index 18ce825..2e0c6d2 100644 --- a/src/main/kotlin/com/liftric/dtcp/tasks/RiskScoreTask.kt +++ b/src/main/kotlin/com/liftric/dtcp/tasks/RiskScoreTask.kt @@ -11,7 +11,6 @@ import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.Input import org.gradle.api.tasks.Nested import org.gradle.api.tasks.Optional -import kotlin.time.Duration import kotlin.time.ExperimentalTime abstract class RiskScoreTask : DefaultTask() { @@ -42,18 +41,18 @@ abstract class RiskScoreTask : DefaultTask() { fun riskScoreTask() { val apiKeyValue = apiKey.get() val urlValue = url.get() + val projectUUIDValue = projectUUID.orNull + val projectNameValue = projectName.orNull + val projectVersionValue = projectVersion.orNull val riskScoreValue = riskScore.orNull + if (riskScoreValue == null) { logger.info("Skipping risk score calculation") return } - val projectUUIDValue = projectUUID.orNull - val projectNameValue = projectName.orNull - val projectVersionValue = projectVersion.orNull - val maxRiskScore = riskScoreValue.maxRiskScore.orNull - val timeout = riskScoreValue.timeout.getOrElse(Duration.ZERO) + val timeout = riskScoreValue.timeout.orNull val dt = DependencyTrack(apiKeyValue, urlValue) @@ -67,10 +66,11 @@ abstract class RiskScoreTask : DefaultTask() { else -> throw GradleException("Either projectUUID or projectName and projectVersion must be set") } - dt.analyzeProjectFindings(uuid) - logger.info("Reanalyse triggered, waiting $timeout for analysis to finish") - runBlocking { - delay(timeout) + if (timeout != null) { + runBlocking { + logger.info("waiting $timeout before getting risk score") + delay(timeout) + } } val updatedProject = dt.getProject(uuid)