diff --git a/README.md b/README.md index 8d2f37c..d1f4566 100644 --- a/README.md +++ b/README.md @@ -150,3 +150,5 @@ configure { format = org.owasp.dependencycheck.reporting.ReportGenerator.Format.ALL.toString() } ``` + + \ No newline at end of file diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/DependencyCheckPlugin.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/DependencyCheckPlugin.groovy index cd72554..b065629 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/DependencyCheckPlugin.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/DependencyCheckPlugin.groovy @@ -61,11 +61,11 @@ class DependencyCheckPlugin implements Plugin { } void initializeConfigurations(Project project) { - project.extensions.create(CHECK_EXTENSION_NAME, DependencyCheckExtension, project) + project.extensions.create(CHECK_EXTENSION_NAME, DependencyCheckExtension, project, project.objects) } void registerTasks(Project project) { - if (REGISTER_TASK_GRADLE_VERSION.compareTo(GradleVersion.current())<=0) { + if (REGISTER_TASK_GRADLE_VERSION.compareTo(GradleVersion.current()) <= 0) { project.tasks.register(PURGE_TASK, Purge) project.tasks.register(UPDATE_TASK, Update) project.tasks.register(ANALYZE_TASK, Analyze) diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AdditionalCpe.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AdditionalCpe.groovy index 1537c48..af6576a 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AdditionalCpe.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AdditionalCpe.groovy @@ -1,6 +1,12 @@ package org.owasp.dependencycheck.gradle.extension import org.gradle.api.Named +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject /** * Holder for the information regarding an additional CPE to be checked. @@ -8,22 +14,48 @@ import org.gradle.api.Named @groovy.transform.CompileStatic class AdditionalCpe implements Named { - AdditionalCpe(String name) { - this.name = name; - } + private final String name + private final Property description + private final Property cpe + + @Inject + AdditionalCpe(String name, ObjectFactory objects) { + this.name = name + this.description = objects.property(String) + this.cpe = objects.property(String) + } + + /** + * Name assigned to the CPE entry during configuration. + */ + @Override + String getName() { + return name + } + + /** + * Description for the what the CPE represents. + */ + @Input + @Optional + Property getDescription() { + return description + } - /** - * Name assigned to the CPE entry during configuration. - */ - String name; + void setDescription(String value) { + description.set(value) + } - /** - * Description for the what the CPE represents. - */ - String description + /** + * The CPE to be checked against the database. + */ + @Input + @Optional + Property getCpe() { + return cpe + } - /** - * The CPE to be checked against the database. - */ - String cpe + void setCpe(String value) { + cpe.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AnalyzerExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AnalyzerExtension.groovy index e07c28b..947f800 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AnalyzerExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/AnalyzerExtension.groovy @@ -19,6 +19,9 @@ package org.owasp.dependencycheck.gradle.extension import org.gradle.api.Action import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory + +import javax.inject.Inject /** * The analyzer configuration extension. Any value not configured will use the dependency-check-core defaults. @@ -26,8 +29,15 @@ import org.gradle.api.Project @groovy.transform.CompileStatic class AnalyzerExtension { - AnalyzerExtension(Project project) { + @Inject + AnalyzerExtension(Project project, ObjectFactory objects) { this.project = project; + kev = objects.newInstance(KEVExtension, objects) + retirejs = objects.newInstance(RetireJSExtension, objects) + nodeAudit = objects.newInstance(NodeAuditExtension, objects) + nodePackage = objects.newInstance(NodePackageExtension, objects) + artifactory = objects.newInstance(ArtifactoryExtension, objects) + ossIndex = objects.newInstance(OssIndexExtension, objects) } Project project; @@ -178,32 +188,32 @@ class AnalyzerExtension { /** * The configuration extension for known exploited vulnerabilities settings. */ - KEVExtension kev = new KEVExtension() + KEVExtension kev /** * The configuration extension for retirejs settings. */ - RetireJSExtension retirejs = new RetireJSExtension() + RetireJSExtension retirejs /** * The configuration extension for the node audit settings. */ - NodeAuditExtension nodeAudit = new NodeAuditExtension() + NodeAuditExtension nodeAudit /** * The configuration extension for the node package settings. */ - NodePackageExtension nodePackage = new NodePackageExtension() + NodePackageExtension nodePackage /** * The configuration extension for artifactory settings. */ - ArtifactoryExtension artifactory = new ArtifactoryExtension() + ArtifactoryExtension artifactory /** * The configuration extension for artifactory settings. */ - OssIndexExtension ossIndex = new OssIndexExtension() + OssIndexExtension ossIndex /** * Allows programmatic configuration of the KEV extension diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ArtifactoryExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ArtifactoryExtension.groovy index 2b816fc..622c12d 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ArtifactoryExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ArtifactoryExtension.groovy @@ -17,37 +17,126 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The artifactory analyzer configuration. */ @groovy.transform.CompileStatic class ArtifactoryExtension { + + private final Property enabled + private final Property url + private final Property usesProxy + private final Property parallelAnalysis + private final Property username + private final Property apiToken + private final Property bearerToken + + @Inject + ArtifactoryExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.url = objects.property(String) + this.usesProxy = objects.property(Boolean) + this.parallelAnalysis = objects.property(Boolean) + this.username = objects.property(String) + this.apiToken = objects.property(String) + this.bearerToken = objects.property(String) + } + /** * Sets whether the Artifactory Analyzer should be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * The Artifactory server URL. */ - String url + @Input + @Optional + Property getUrl() { + return url + } + + void setUrl(String value) { + url.set(value) + } + /** * Whether Artifactory should be accessed through a proxy or not. */ - Boolean usesProxy + @Input + @Optional + Property getUsesProxy() { + return usesProxy + } + + void setUsesProxy(Boolean value) { + usesProxy.set(value) + } + /** * Whether the Artifactory analyzer should be run in parallel or not. */ - Boolean parallelAnalysis + @Input + @Optional + Property getParallelAnalysis() { + return parallelAnalysis + } + + void setParallelAnalysis(Boolean value) { + parallelAnalysis.set(value) + } + /** * The user name (only used with API token) to connect to Artifactory instance. */ - String username + @Input + @Optional + Property getUsername() { + return username + } + + void setUsername(String value) { + username.set(value) + } + /** * The API token to connect to Artifactory instance. */ - String apiToken + @Input + @Optional + Property getApiToken() { + return apiToken + } + + void setApiToken(String value) { + apiToken.set(value) + } + /** * The bearer token to connect to Artifactory instance. */ - String bearerToken + @Input + @Optional + Property getBearerToken() { + return bearerToken + } + + void setBearerToken(String value) { + bearerToken.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/CacheExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/CacheExtension.groovy index 515f2f7..b4e7dce 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/CacheExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/CacheExtension.groovy @@ -17,24 +17,69 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The configuration for caching external results. */ @groovy.transform.CompileStatic class CacheExtension { + + private final Property ossIndex + private final Property central + private final Property nodeAudit + + @Inject + CacheExtension(ObjectFactory objects) { + this.ossIndex = objects.property(Boolean) + this.central = objects.property(Boolean) + this.nodeAudit = objects.property(Boolean) + } + /** * Sets whether the OSS Index Analyzer's results should be cached locally. * Cache expires after 24 hours. */ - Boolean ossIndex + @Input + @Optional + Property getOssIndex() { + return ossIndex + } + + void setOssIndex(Boolean value) { + ossIndex.set(value) + } + /** * Sets whether the Central Analyzer's results should be cached locally. * Cache expires after 30 days. */ - Boolean central + @Input + @Optional + Property getCentral() { + return central + } + + void setCentral(Boolean value) { + central.set(value) + } + /** * Sets whether the Node Audit Analyzer's results should be cached locally. * Cache expires after 24 hours. */ - Boolean nodeAudit + @Input + @Optional + Property getNodeAudit() { + return nodeAudit + } + + void setNodeAudit(Boolean value) { + nodeAudit.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DataExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DataExtension.groovy index 7cfb9b0..72fb34b 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DataExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DataExtension.groovy @@ -19,39 +19,112 @@ package org.owasp.dependencycheck.gradle.extension import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject /** * The update data configuration extension. Any value not configured will use the dependency-check-core defaults. */ @groovy.transform.CompileStatic class DataExtension { - - DataExtension(Project project) { - directory = "${project.gradle.gradleUserHomeDir}/dependency-check-data/11.0" + + private final Property directory + private final Property connectionString + private final Property username + private final Property password + private final Property driver + private final Property driverPath + + @Inject + DataExtension(ObjectFactory objects, Project project) { + this.directory = objects.property(String) + this.directory.set("${project.gradle.gradleUserHomeDir}/dependency-check-data/11.0".toString()) + this.connectionString = objects.property(String) + this.username = objects.property(String) + this.password = objects.property(String) + this.driver = objects.property(String) + this.driverPath = objects.property(String) } /** * The directory to store the H2 database that contains the cache of the NVD CVE data. */ - String directory; + @Input + @Optional + Property getDirectory() { + return directory + } + + void setDirectory(String value) { + directory.set(value) + } + /** * The connection string to the database. */ - String connectionString + @Input + @Optional + Property getConnectionString() { + return connectionString + } + + void setConnectionString(String value) { + connectionString.set(value) + } + /** * The user name to use when connecting to the database. */ - String username + @Input + @Optional + Property getUsername() { + return username + } + + void setUsername(String value) { + username.set(value) + } + /** * The password to use when connecting to the database. */ - String password + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + /** * The database driver name (e.g. org.h2.Driver). */ - String driver + @Input + @Optional + Property getDriver() { + return driver + } + + void setDriver(String value) { + driver.set(value) + } + /** * The path to the driver (JAR) in case it is not already in the classpath. */ - String driverPath + @Input + @Optional + Property getDriverPath() { + return driverPath + } + + void setDriverPath(String value) { + driverPath.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DependencyCheckExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DependencyCheckExtension.groovy index 20499c6..c58488a 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DependencyCheckExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/DependencyCheckExtension.groovy @@ -21,7 +21,17 @@ package org.owasp.dependencycheck.gradle.extension import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project - +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Optional + +import javax.inject.Inject import java.util.stream.Collectors import static org.owasp.dependencycheck.reporting.ReportGenerator.Format @@ -36,103 +46,285 @@ import static org.owasp.dependencycheck.reporting.ReportGenerator.Format @groovy.transform.CompileStatic class DependencyCheckExtension { - DependencyCheckExtension(Project project) { - this.project = project; - outputDirectory = "${project.buildDir}/reports" - } - Project project; + private final Property scanBuildEnv + private final Property scanDependencies + private final Property failOnError + private final Property quickQueryTimestamp + private final DirectoryProperty outputDirectory + private final Property suppressionFile + private final ListProperty suppressionFiles + private final Property suppressionFileUser + private final Property suppressionFilePassword + private final Property suppressionFileBearerToken + private final Property hintsFile + private final Property autoUpdate + private final Property skipTestGroups + private final Property format + private final ListProperty formats + private final Property failBuildOnCVSS + private final Property junitFailOnCVSS + private final Property failBuildOnUnusedSuppressionRule + private final Property showSummary + private final ListProperty scanConfigurations + private final ListProperty skipConfigurations + private final ListProperty scanProjects + private final ListProperty skipProjects + private final ListProperty skipGroups + private final ListProperty analyzedTypes + private final Property skip + private final ConfigurableFileCollection scanSet + /** - * Whether the buildEnv should be analyzed. + * The configuration extension for proxy settings. */ - Boolean scanBuildEnv = false + ProxyExtension proxy /** - * Whether the dependencies should be analyzed. + * The configuration extension for slack notifications. */ - Boolean scanDependencies = true + SlackExtension slack + /** - * The configuration extension for proxy settings. + * The configuration extension that defines the location of the NVD CVE data. */ - ProxyExtension proxy = new ProxyExtension() + NvdExtension nvd + /** - * The configuration extension for proxy settings. + * The configuration extension that configures the hosted suppressions file. */ - SlackExtension slack = new SlackExtension() + HostedSuppressionsExtension hostedSuppressions /** - * The configuration extension that defines the location of the NVD CVE data. + * The configuration extension for data related configuration options. */ - NvdExtension nvd = new NvdExtension() + DataExtension data /** - * The configuration extension that configures the hosted suppressions file. + * Configuration for the analyzers. */ - HostedSuppressionsExtension hostedSuppressions = new HostedSuppressionsExtension() + AnalyzerExtension analyzers /** - * Whether the plugin should fail when errors occur. + * Additional CPE to be analyzed. */ - Boolean failOnError = true + NamedDomainObjectContainer additionalCpes + /** - * The configuration extension for data related configuration options. + * The configuration extension for cache settings. */ - DataExtension data = new DataExtension(project) + CacheExtension cache + + @Inject + DependencyCheckExtension(Project project, ObjectFactory objects) { + this.project = project; + + this.scanBuildEnv = objects.property(Boolean).convention(false) + this.scanDependencies = objects.property(Boolean).convention(true) + this.failOnError = objects.property(Boolean).convention(true) + this.quickQueryTimestamp = objects.property(Boolean) + this.outputDirectory = objects.directoryProperty().convention(project.layout.buildDirectory.dir("reports")) + this.suppressionFile = objects.property(String) + this.suppressionFiles = objects.listProperty(String).convention([]) + this.suppressionFileUser = objects.property(String) + this.suppressionFilePassword = objects.property(String) + this.suppressionFileBearerToken = objects.property(String) + this.hintsFile = objects.property(String) + this.autoUpdate = objects.property(Boolean) + this.skipTestGroups = objects.property(Boolean).convention(true) + this.format = objects.property(String).convention(Format.HTML.toString()) + this.formats = objects.listProperty(String).convention([]) + this.failBuildOnCVSS = objects.property(Float).convention(11.0f) + this.junitFailOnCVSS = objects.property(Float).convention(0.0f) + this.failBuildOnUnusedSuppressionRule = objects.property(Boolean).convention(false) + this.showSummary = objects.property(Boolean).convention(true) + this.scanConfigurations = objects.listProperty(String).convention([]) + this.skipConfigurations = objects.listProperty(String).convention([]) + this.scanProjects = objects.listProperty(String).convention([]) + this.skipProjects = objects.listProperty(String).convention([]) + this.skipGroups = objects.listProperty(String).convention([]) + this.analyzedTypes = objects.listProperty(String).convention(['jar', 'aar', 'js', 'war', 'ear', 'zip']) + this.skip = objects.property(Boolean).convention(false) + this.scanSet = objects.fileCollection() + + cache = objects.newInstance(CacheExtension, objects) + slack = objects.newInstance(SlackExtension, objects) + proxy = objects.newInstance(ProxyExtension, objects) + nvd = objects.newInstance(NvdExtension, objects) + hostedSuppressions = objects.newInstance(HostedSuppressionsExtension, objects) + data = objects.newInstance(DataExtension, objects, project) + analyzers = new AnalyzerExtension(project, objects) + additionalCpes = project.objects.domainObjectContainer(AdditionalCpe.class) + } /** - * Set to false if the proxy does not support HEAD requests. The default is true. + * Whether the buildEnv should be analyzed. */ - Boolean quickQueryTimestamp + @Input + @Optional + Property getScanBuildEnv() { + return scanBuildEnv + } + + void setScanBuildEnv(Boolean value) { + scanBuildEnv.set(value) + } + /** - * The directory where the reports will be written. Defaults to 'build/reports'. + * Whether the dependencies should be analyzed. */ - String outputDirectory + @Input + @Optional + Property getScanDependencies() { + return scanDependencies + } + + void setScanDependencies(Boolean value) { + scanDependencies.set(value) + } + /** - * Configuration for the analyzers. + * Whether the plugin should fail when errors occur. + */ + @Input + @Optional + Property getFailOnError() { + return failOnError + } + + void setFailOnError(Boolean value) { + failOnError.set(value) + } + + /** + * Set to false if the proxy does not support HEAD requests. The default is true. */ - AnalyzerExtension analyzers = new AnalyzerExtension(project) + @Input + @Optional + Property getQuickQueryTimestamp() { + return quickQueryTimestamp + } + + void setQuickQueryTimestamp(Boolean value) { + quickQueryTimestamp.set(value) + } + + /** + * The directory where the reports will be written. Defaults to 'build/reports'. + */ + @InputDirectory + @Optional + DirectoryProperty getOutputDirectory() { + return outputDirectory + } + + void setOutputDirectory(String value) { + outputDirectory.set(project.file(value)) + } + + void setOutputDirectory(File value) { + outputDirectory.set(value) + } + /** * The path to the suppression file. */ - String suppressionFile + @Input + @Optional + Property getSuppressionFile() { + return suppressionFile + } + + void setSuppressionFile(String value) { + suppressionFile.set(value) + } + /** * The list of paths to suppression files. */ - Collection suppressionFiles = []; + @Input + @Optional + ListProperty getSuppressionFiles() { + return suppressionFiles + } - public void setSuppressionFiles(java.lang.Object[] files) { + void setSuppressionFiles(java.lang.Object[] files) { if (files != null) { - suppressionFiles = Arrays.stream(files).map({ o -> o.toString() }).collect(Collectors.toSet()) + suppressionFiles.set(Arrays.stream(files).map({ o -> o.toString() }).collect(Collectors.toList())) } } - public void setSuppressionFiles(Collection files) { + + void setSuppressionFiles(Collection files) { if (files != null) { - suppressionFiles = files; + suppressionFiles.set(files.toList()) } } + /** * The username for downloading the suppression file(s) from HTTP Basic protected locations */ - String suppressionFileUser + @Input + @Optional + Property getSuppressionFileUser() { + return suppressionFileUser + } + + void setSuppressionFileUser(String value) { + suppressionFileUser.set(value) + } + /** * The password for downloading the suppression file(s) from HTTP Basic protected locations */ - String suppressionFilePassword + @Input + @Optional + Property getSuppressionFilePassword() { + return suppressionFilePassword + } + + void setSuppressionFilePassword(String value) { + suppressionFilePassword.set(value) + } + /** * The token for downloading the suppression file(s) from HTTP Bearer protected locations */ - String suppressionFileBearerToken + @Input + @Optional + Property getSuppressionFileBearerToken() { + return suppressionFileBearerToken + } + + void setSuppressionFileBearerToken(String value) { + suppressionFileBearerToken.set(value) + } + /** * The path to the hints file. */ - String hintsFile + @Input + @Optional + Property getHintsFile() { + return hintsFile + } + + void setHintsFile(String value) { + hintsFile.set(value) + } + /** * Sets whether auto-updating of the NVD CVE/CPE data is enabled. */ - Boolean autoUpdate + @Input + @Optional + Property getAutoUpdate() { + return autoUpdate + } + + void setAutoUpdate(Boolean value) { + autoUpdate.set(value) + } - //The following properties are not used via the settings object, instead - // they are directly used by the check task. /** * When set to true configurations that are considered a test configuration will not be included in the analysis. * A configuration is considered a test configuration if and only if any of the following conditions holds: @@ -145,87 +337,215 @@ class DependencyCheckExtension { * * The default value is true. */ - Boolean skipTestGroups = true + @Input + @Optional + Property getSkipTestGroups() { + return skipTestGroups + } + + void setSkipTestGroups(Boolean value) { + skipTestGroups.set(value) + } + /** * The report format to be generated (HTML, XML, CSV, JUNIT, SARIF, ALL). This configuration option has * no affect if using this within the Site plugin unless the externalReport is set to true. * The default is HTML. */ - String format = Format.HTML.toString() + @Input + @Optional + Property getFormat() { + return format + } + + void setFormat(String value) { + format.set(value) + } + /** * The list of formats to generate to report (HTML, XML, CSV, JUNIT, SARIF, ALL). */ - List formats = [] + @Input + @Optional + ListProperty getFormats() { + return formats + } + + void setFormats(List value) { + formats.set(value) + } + /** * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is * 11 which means since the CVSS scores are 0-10, by default the build will never fail. */ - Float failBuildOnCVSS = 11.0f + @Input + @Optional + Property getFailBuildOnCVSS() { + return failBuildOnCVSS + } + + void setFailBuildOnCVSS(Number value) { + failBuildOnCVSS.set(value?.floatValue()) +} + /** * Specifies the CVSS score that should be considered a failure when generating a JUNIT formatted report. The default * is 0.0 which means all identified vulnerabilities would be considered a failure. */ - Float junitFailOnCVSS = 0.0f + @Input + @Optional + Property getJunitFailOnCVSS() { + return junitFailOnCVSS + } + + void setJunitFailOnCVSS(Number value) { + junitFailOnCVSS.set(value?.floatValue()) +} + /** * Specifies that if any unused suppression rule is found, the build will fail. */ - Boolean failBuildOnUnusedSuppressionRule = false + @Input + @Optional + Property getFailBuildOnUnusedSuppressionRule() { + return failBuildOnUnusedSuppressionRule + } + + void setFailBuildOnUnusedSuppressionRule(Boolean value) { + failBuildOnUnusedSuppressionRule.set(value) + } + /** * Displays a summary of the findings. Defaults to true. */ - Boolean showSummary = true + @Input + @Optional + Property getShowSummary() { + return showSummary + } + + void setShowSummary(Boolean value) { + showSummary.set(value) + } + /** * Names of the configurations to scan. * * This is mutually exclusive with the skipConfigurations property. */ - List scanConfigurations = [] + @Input + @Optional + ListProperty getScanConfigurations() { + return scanConfigurations + } + + void setScanConfigurations(List value) { + scanConfigurations.set(value) + } + /** * Names of the configurations to skip when scanning. * * This is mutually exclusive with the scanConfigurations property. */ - List skipConfigurations = [] + @Input + @Optional + ListProperty getSkipConfigurations() { + return skipConfigurations + } + + void setSkipConfigurations(List value) { + skipConfigurations.set(value) + } + /** * Paths of the projects to scan. * * This is mutually exclusive with the skipProjects property. */ - List scanProjects = [] + @Input + @Optional + ListProperty getScanProjects() { + return scanProjects + } + + void setScanProjects(List value) { + scanProjects.set(value) + } + /** * Paths of the projects to skip when scanning. * * This is mutually exclusive with the scanProjects property. */ - List skipProjects = [] + @Input + @Optional + ListProperty getSkipProjects() { + return skipProjects + } + + void setSkipProjects(List value) { + skipProjects.set(value) + } + /** * Group prefixes of the modules to skip when scanning. * * The 'project' prefix can be used to skip all internal dependencies from multi-project build. */ - List skipGroups = [] + @Input + @Optional + ListProperty getSkipGroups() { + return skipGroups + } + + void setSkipGroups(List value) { + skipGroups.set(value) + } + /** * The artifact types that will be analyzed in the gradle build. */ - List analyzedTypes = ['jar', 'aar', 'js', 'war', 'ear', 'zip'] + @Input + @Optional + ListProperty getAnalyzedTypes() { + return analyzedTypes + } + + void setAnalyzedTypes(List value) { + analyzedTypes.set(value) + } + /** * whether to skip the execution of dependency-check. */ - Boolean skip = false + @Input + @Optional + Property getSkip() { + return skip + } + + void setSkip(Boolean value) { + skip.set(value) + } + /** * A set of files or folders to scan. */ - List scanSet - /** - * Additional CPE to be analyzed. - */ - NamedDomainObjectContainer additionalCpes = - project.objects.domainObjectContainer(AdditionalCpe.class) + @InputFiles + @Optional + ConfigurableFileCollection getScanSet() { + return scanSet + } - /** - * The configuration extension for cache settings. - */ - CacheExtension cache = new CacheExtension() + void setScanSet(List files) { + scanSet.setFrom(files) + } + + void setScanSet(File... files) { + scanSet.setFrom(files) + } /** diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/HostedSuppressionsExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/HostedSuppressionsExtension.groovy index 6c08c23..41d2bc1 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/HostedSuppressionsExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/HostedSuppressionsExtension.groovy @@ -1,35 +1,125 @@ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The advanced configuration for the hosted suppressions file. */ +@groovy.transform.CompileStatic class HostedSuppressionsExtension { + + private final Property enabled + private final Property url + private final Property user + private final Property password + private final Property bearerToken + private final Property forceupdate + private final Property validForHours + + @Inject + HostedSuppressionsExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.url = objects.property(String) + this.user = objects.property(String) + this.password = objects.property(String) + this.bearerToken = objects.property(String) + this.forceupdate = objects.property(Boolean) + this.validForHours = objects.property(Integer) + } + /** * Whether the hosted suppressions fie will be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * The URL for a mirrored hosted suppressions file. */ - String url + @Input + @Optional + Property getUrl() { + return url + } + + void setUrl(String value) { + url.set(value) + } + /** * Credentials used for basic authentication for a mirrored hosted suppressions file. */ - String user + @Input + @Optional + Property getUser() { + return user + } + + void setUser(String value) { + user.set(value) + } + /** * Credentials used for basic authentication for a mirrored hosted suppressions file. */ - String password + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + /** * Credentials used for bearer authentication for a mirrored hosted suppressions file. */ - String bearerToken + @Input + @Optional + Property getBearerToken() { + return bearerToken + } + + void setBearerToken(String value) { + bearerToken.set(value) + } + /** * Whether the hosted suppressions file should be updated regardless of the `autoupdate` setting. */ - Boolean forceupdate + @Input + @Optional + Property getForceupdate() { + return forceupdate + } + + void setForceupdate(Boolean value) { + forceupdate.set(value) + } + /** * The number of hours to wait before checking for changes in the hosted suppressions file. */ - Integer validForHours + @Input + @Optional + Property getValidForHours() { + return validForHours + } + + void setValidForHours(Number value) { + validForHours.set(value?.intValue()) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/KEVExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/KEVExtension.groovy index 121c772..47a456b 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/KEVExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/KEVExtension.groovy @@ -1,28 +1,107 @@ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + +@groovy.transform.CompileStatic class KEVExtension { + + private final Property enabled + private final Property url + private final Property user + private final Property password + private final Property bearerToken + private final Property validForHours + + @Inject + KEVExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.url = objects.property(String) + this.user = objects.property(String) + this.password = objects.property(String) + this.bearerToken = objects.property(String) + this.validForHours = objects.property(Integer) + } + /** * Sets whether the Known Exploited Vulnerability update and Analyzer will be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * URL to the CISA Known Exploited Vulnerabilities JSON data feed. */ - String url + @Input + @Optional + Property getUrl() { + return url + } + + void setUrl(String value) { + url.set(value) + } + /** * Credentials used for basic authentication for the CISA Known Exploited Vulnerabilities JSON data feed. */ - String user + @Input + @Optional + Property getUser() { + return user + } + + void setUser(String value) { + user.set(value) + } + /** * Credentials used for basic authentication for the CISA Known Exploited Vulnerabilities JSON data feed. */ - String password + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + /** * Credentials used for bearer authentication for the CISA Known Exploited Vulnerabilities JSON data feed. */ - String bearerToken + @Input + @Optional + Property getBearerToken() { + return bearerToken + } + + void setBearerToken(String value) { + bearerToken.set(value) + } + /** * Controls the skipping of the check for Known Exploited Vulnerabilities updates. */ - Integer validForHours + @Input + @Optional + Property getValidForHours() { + return validForHours + } + + void setValidForHours(Number value) { + validForHours.set(value?.intValue()) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodeAuditExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodeAuditExtension.groovy index 2566887..3ea27af 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodeAuditExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodeAuditExtension.groovy @@ -17,41 +17,141 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The configuration for the Node Audit Analyzer. */ @groovy.transform.CompileStatic class NodeAuditExtension { + + private final Property enabled + private final Property useCache + private final Property skipDevDependencies + private final Property yarnEnabled + private final Property yarnPath + private final Property pnpmEnabled + private final Property pnpmPath + private final Property url + + @Inject + NodeAuditExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.useCache = objects.property(Boolean) + this.skipDevDependencies = objects.property(Boolean) + this.yarnEnabled = objects.property(Boolean) + this.yarnPath = objects.property(String) + this.pnpmEnabled = objects.property(Boolean) + this.pnpmPath = objects.property(String) + this.url = objects.property(String) + } + /** * Sets whether the Node Audit Analyzer should be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * Sets whether the Node Audit Analyzer should cache results locally. */ - Boolean useCache + @Input + @Optional + Property getUseCache() { + return useCache + } + + void setUseCache(Boolean value) { + useCache.set(value) + } + /** * Sets whether the Node Audit Analyzer should skip devDependencies. */ - Boolean skipDevDependencies + @Input + @Optional + Property getSkipDevDependencies() { + return skipDevDependencies + } + + void setSkipDevDependencies(Boolean value) { + skipDevDependencies.set(value) + } + /** * Sets whether the Yarn Audit Analyzer should be used. */ - Boolean yarnEnabled + @Input + @Optional + Property getYarnEnabled() { + return yarnEnabled + } + + void setYarnEnabled(Boolean value) { + yarnEnabled.set(value) + } + /** * The path to `yarn`. */ - String yarnPath + @Input + @Optional + Property getYarnPath() { + return yarnPath + } + + void setYarnPath(String value) { + yarnPath.set(value) + } + /** * Sets whether the Pnpm Audit Analyzer should be used. */ - Boolean pnpmEnabled + @Input + @Optional + Property getPnpmEnabled() { + return pnpmEnabled + } + + void setPnpmEnabled(Boolean value) { + pnpmEnabled.set(value) + } + /** * The path to `pnpm`. */ - String pnpmPath + @Input + @Optional + Property getPnpmPath() { + return pnpmPath + } + + void setPnpmPath(String value) { + pnpmPath.set(value) + } + /** * The URL to the NPM Audit API. */ - String url + @Input + @Optional + Property getUrl() { + return url + } + + void setUrl(String value) { + url.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodePackageExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodePackageExtension.groovy index 1e7544f..83edae9 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodePackageExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NodePackageExtension.groovy @@ -17,17 +17,51 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The configuration for the Node Package Analyzer. */ @groovy.transform.CompileStatic class NodePackageExtension { + + private final Property enabled + private final Property skipDevDependencies + + @Inject + NodePackageExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.skipDevDependencies = objects.property(Boolean) + } + /** * Sets whether the Node Package Analyzer should be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * Sets whether the Node Package Analyzer should skip devDependencies. */ - Boolean skipDevDependencies + @Input + @Optional + Property getSkipDevDependencies() { + return skipDevDependencies + } + + void setSkipDevDependencies(Boolean value) { + skipDevDependencies.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NvdExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NvdExtension.groovy index a1343c4..e192083 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NvdExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/NvdExtension.groovy @@ -16,52 +16,185 @@ * Copyright (c) 2023 Jeremy Long. All Rights Reserved. */ -package org.owasp.dependencycheck.gradle.extension; +package org.owasp.dependencycheck.gradle.extension + +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject @groovy.transform.CompileStatic class NvdExtension { + + private final Property apiKey + private final Property delay + private final Property resultsPerPage + private final Property maxRetryCount + private final Property datafeedUrl + private final Property datafeedUser + private final Property datafeedPassword + private final Property datafeedBearerToken + private final Property datafeedStartYear + private final Property validForHours + private final Property endpoint + + @Inject + NvdExtension(ObjectFactory objects) { + this.apiKey = objects.property(String) + this.delay = objects.property(Integer) + this.resultsPerPage = objects.property(Integer) + this.maxRetryCount = objects.property(Integer) + this.datafeedUrl = objects.property(String) + this.datafeedUser = objects.property(String) + this.datafeedPassword = objects.property(String) + this.datafeedBearerToken = objects.property(String) + this.datafeedStartYear = objects.property(Integer) + this.validForHours = objects.property(Integer) + this.endpoint = objects.property(String) + } + /** * The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key. */ - String apiKey + @Input + @Optional + Property getApiKey() { + return apiKey + } + + void setApiKey(String value) { + apiKey.set(value) + } + /** * The number of milliseconds to wait between calls to the NVD API. */ - Integer delay + @Input + @Optional + Property getDelay() { + return delay + } + + void setDelay(Number value) { + delay.set(value?.intValue()) + } + /** * The number records for a single page from NVD API (must be <=2000). */ - Integer resultsPerPage + @Input + @Optional + Property getResultsPerPage() { + return resultsPerPage + } + + void setResultsPerPage(Number value) { + resultsPerPage.set(value?.intValue()) + } + /** * The maximum number of retry requests for a single call to the NVD API. */ - Integer maxRetryCount + @Input + @Optional + Property getMaxRetryCount() { + return maxRetryCount + } + + void setMaxRetryCount(Number value) { + maxRetryCount.set(value?.intValue()) + } + /** * The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/Open-Vulnerability-Project/tree/main/vulnz#caching-the-nvd-cve-data. */ - String datafeedUrl + @Input + @Optional + Property getDatafeedUrl() { + return datafeedUrl + } + + void setDatafeedUrl(String value) { + datafeedUrl.set(value) + } + /** * Credentials used for basic authentication for the NVD API Data feed. */ - String datafeedUser + @Input + @Optional + Property getDatafeedUser() { + return datafeedUser + } + + void setDatafeedUser(String value) { + datafeedUser.set(value) + } + /** * Credentials used for basic authentication for the NVD API Data feed. */ - String datafeedPassword + @Input + @Optional + Property getDatafeedPassword() { + return datafeedPassword + } + + void setDatafeedPassword(String value) { + datafeedPassword.set(value) + } + /** * Credentials used for bearer authentication for the NVD API Data feed. */ - String datafeedBearerToken + @Input + @Optional + Property getDatafeedBearerToken() { + return datafeedBearerToken + } + + void setDatafeedBearerToken(String value) { + datafeedBearerToken.set(value) + } + /** * The starting year for the NVD CVE Data feed cache. */ - Integer datafeedStartYear + @Input + @Optional + Property getDatafeedStartYear() { + return datafeedStartYear + } + + void setDatafeedStartYear(Number value) { + datafeedStartYear.set(value?.intValue()) + } + /** * The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. */ - Integer validForHours + @Input + @Optional + Property getValidForHours() { + return validForHours + } + + void setValidForHours(Number value) { + validForHours.set(value?.intValue()) + } + /** * The NVD API endpoint URL; configuring this is uncommon. */ - String endpoint; + @Input + @Optional + Property getEndpoint() { + return endpoint + } + + void setEndpoint(String value) { + endpoint.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/OssIndexExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/OssIndexExtension.groovy index 61cbcea..9c50c5b 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/OssIndexExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/OssIndexExtension.groovy @@ -17,29 +17,96 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The configuration for the OSS Index Analyzer. */ @groovy.transform.CompileStatic class OssIndexExtension { + + private final Property enabled + private final Property username + private final Property password + private final Property url + private final Property warnOnlyOnRemoteErrors + + @Inject + OssIndexExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.username = objects.property(String) + this.password = objects.property(String) + this.url = objects.property(String) + this.warnOnlyOnRemoteErrors = objects.property(Boolean) + } + /** * Sets whether the OSS Index Analyzer should be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * The optional username to connect to the OSS Index */ - String username + @Input + @Optional + Property getUsername() { + return username + } + + void setUsername(String value) { + username.set(value) + } + /** * The optional password or API token to connect to the OSS Index */ - String password + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + /** * The OSS Index URL. */ - String url + @Input + @Optional + Property getUrl() { + return url + } + + void setUrl(String value) { + url.set(value) + } + /** * Only output a warning message instead of failing when remote errors occur. */ - Boolean warnOnlyOnRemoteErrors + @Input + @Optional + Property getWarnOnlyOnRemoteErrors() { + return warnOnlyOnRemoteErrors + } + + void setWarnOnlyOnRemoteErrors(Boolean value) { + warnOnlyOnRemoteErrors.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ProxyExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ProxyExtension.groovy index f99d811..610e6a2 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ProxyExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/ProxyExtension.groovy @@ -17,6 +17,15 @@ */ package org.owasp.dependencycheck.gradle.extension + +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * TODO - this should not be needed, instead rely on the configured HTTP or HTTPS proxies * https://docs.gradle.org/current/userguide/build_environment.html @@ -24,9 +33,69 @@ package org.owasp.dependencycheck.gradle.extension @Deprecated @groovy.transform.CompileStatic class ProxyExtension { - String server - Integer port - String username - String password - List nonProxyHosts = [] + + private final Property server + private final Property port + private final Property username + private final Property password + private final ListProperty nonProxyHosts + + @Inject + ProxyExtension(ObjectFactory objects) { + this.server = objects.property(String) + this.port = objects.property(Integer) + this.username = objects.property(String) + this.password = objects.property(String) + this.nonProxyHosts = objects.listProperty(String).empty() + } + + @Input + @Optional + Property getServer() { + return server + } + + void setServer(String value) { + server.set(value) + } + + @Input + @Optional + Property getPort() { + return port + } + + void setPort(Number value) { + port.set(value?.intValue()) + } + + @Input + @Optional + Property getUsername() { + return username + } + + void setUsername(String value) { + username.set(value) + } + + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + + @Input + @Optional + ListProperty getNonProxyHosts() { + return nonProxyHosts + } + + void setNonProxyHosts(List value) { + nonProxyHosts.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/RetireJSExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/RetireJSExtension.groovy index d01bc74..bb0e15c 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/RetireJSExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/RetireJSExtension.groovy @@ -17,42 +17,143 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** * The configuration for the RetireJS Analyzer. */ @groovy.transform.CompileStatic class RetireJSExtension { + + private final Property enabled + private final ListProperty filters + private final Property filterNonVulnerable + private final Property retireJsUrl + private final Property user + private final Property password + private final Property bearerToken + private final Property forceupdate + + @Inject + RetireJSExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.filters = objects.listProperty(String).empty() + this.filterNonVulnerable = objects.property(Boolean) + this.retireJsUrl = objects.property(String) + this.user = objects.property(String) + this.password = objects.property(String) + this.bearerToken = objects.property(String) + this.forceupdate = objects.property(Boolean) + } + /** * Sets whether the RetireJS Analyzer should be used. */ - Boolean enabled + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + /** * The JS content filters (regular expressions) used to filter which JS files will be skipped if the content matches one * of the filters. This is most commonly used to filter by copyright. */ - List filters = [] + @Input + @Optional + ListProperty getFilters() { + return filters + } + + void setFilters(List value) { + filters.set(value) + } + /** * Whether the Retire JS analyzer should filter the non-vunerable JS from the report. */ - Boolean filterNonVulnerable + @Input + @Optional + Property getFilterNonVulnerable() { + return filterNonVulnerable + } + + void setFilterNonVulnerable(Boolean value) { + filterNonVulnerable.set(value) + } + /** * The Retire JS Repository URL. */ - String retireJsUrl + @Input + @Optional + Property getRetireJsUrl() { + return retireJsUrl + } + + void setRetireJsUrl(String value) { + retireJsUrl.set(value) + } + /** * Credentials used for basic authentication for the Retire JS Repository URL. */ - String user + @Input + @Optional + Property getUser() { + return user + } + + void setUser(String value) { + user.set(value) + } + /** * Credentials used for basic authentication for the Retire JS Repository URL. */ - String password + @Input + @Optional + Property getPassword() { + return password + } + + void setPassword(String value) { + password.set(value) + } + /** * Credentials used for bearer authentication for the Retire JS Repository URL. */ - String bearerToken + @Input + @Optional + Property getBearerToken() { + return bearerToken + } + + void setBearerToken(String value) { + bearerToken.set(value) + } + /** * Whether the Retire JS analyzer should be updated regardless of the `autoupdate` setting. */ - Boolean forceupdate + @Input + @Optional + Property getForceupdate() { + return forceupdate + } + + void setForceupdate(Boolean value) { + forceupdate.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/SlackExtension.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/SlackExtension.groovy index 402a963..778de0f 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/extension/SlackExtension.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/extension/SlackExtension.groovy @@ -17,11 +17,45 @@ */ package org.owasp.dependencycheck.gradle.extension +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional + +import javax.inject.Inject + /** - * The configuration for the Node Audit Analyzer. + * The configuration for Slack notifications. */ @groovy.transform.CompileStatic class SlackExtension { - Boolean enabled - String webhookUrl + + private final Property enabled + private final Property webhookUrl + + @Inject + SlackExtension(ObjectFactory objects) { + this.enabled = objects.property(Boolean) + this.webhookUrl = objects.property(String) + } + + @Input + @Optional + Property getEnabled() { + return enabled + } + + void setEnabled(Boolean value) { + enabled.set(value) + } + + @Input + @Optional + Property getWebhookUrl() { + return webhookUrl + } + + void setWebhookUrl(String value) { + webhookUrl.set(value) + } } diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/AbstractAnalyze.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/AbstractAnalyze.groovy index af0d130..5369e14 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/AbstractAnalyze.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/AbstractAnalyze.groovy @@ -77,7 +77,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { @TaskAction @groovy.transform.CompileStatic analyze() { - if (config.skip) { + if (config.skip.get()) { logger.lifecycle("Skipping dependency-check-gradle") return } @@ -88,7 +88,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { engine = new Engine(settings) } catch (DatabaseException ex) { String msg = "Unable to connect to the dependency-check database" - if (config.failOnError) { + if (config.failOnError.get()) { cleanup(engine) throw new GradleException(msg, ex) } else { @@ -102,7 +102,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { try { engine.analyzeDependencies() } catch (ExceptionCollection ex) { - if (config.failOnError || ex.isFatal()) { + if (config.failOnError.get() || ex.isFatal()) { cleanup(engine) throw new GradleException("Analysis failed.", ex) } @@ -115,8 +115,8 @@ abstract class AbstractAnalyze extends ConfiguredTask { String displayName = determineDisplayName() String groupId = project.getGroup() String version = project.getVersion().toString() - File output = project.file(config.outputDirectory) - for (String f : getReportFormats(config.format, config.formats)) { + File output = config.outputDirectory.get().asFile + for (String f : getReportFormats(config.format.get(), config.formats.get())) { engine.writeReports(displayName, groupId, name, version, output, f, exCol) } showSummary(engine) @@ -126,7 +126,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { throw new GradleException(result.msg) } } catch (ReportException ex) { - if (config.failOnError) { + if (config.failOnError.get()) { if (exCol != null) { exCol.addException(ex) throw new GradleException("Error generating the report", exCol) @@ -139,7 +139,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { } finally { cleanup(engine) } - if (config.failOnError && exCol != null && exCol.getExceptions().size() > 0) { + if (config.failOnError.get() && exCol != null && exCol.getExceptions().size() > 0) { throw new GradleException("One or more exceptions occurred during analysis", exCol) } } @@ -159,13 +159,13 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic def verifySettings() { - if (!config.scanDependencies && !config.scanBuildEnv) { + if (!config.scanDependencies.get() && !config.scanBuildEnv.get()) { throw new IllegalArgumentException("At least one of scanDependencies or scanBuildEnv must be set to true") } - if (config.scanConfigurations && config.skipConfigurations) { + if (!config.scanConfigurations.get().isEmpty() && !config.skipConfigurations.get().isEmpty()) { throw new IllegalArgumentException("you can only specify one of scanConfigurations or skipConfigurations") } - if (config.scanProjects && config.skipProjects) { + if (!config.scanProjects.get().isEmpty() && !config.skipProjects.get().isEmpty()) { throw new IllegalArgumentException("you can only specify one of scanProjects or skipProjects") } } @@ -231,7 +231,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { }.flatten() logger.warn("Found ${vulnerabilities.size()} vulnerabilities in project ${currentProjectName}") - if (config.showSummary) { + if (config.showSummary.get()) { DependencyCheckScanAgent.showSummary(project.name, engine.getDependencies()); } } @@ -242,7 +242,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic CheckForFailureResult checkForFailure(Engine engine) { - if (config.failBuildOnCVSS > 10) { + if (config.failBuildOnCVSS.get() > 10) { return CheckForFailureResult.createSuccess() } @@ -257,12 +257,12 @@ abstract class AbstractAnalyze extends ConfiguredTask { && v.getCvssV4().getCvssData().getBaseScore() != null ? v.getCvssV4().getCvssData().getBaseScore() : -1; final boolean useUnscored = cvssV2 == -1 && cvssV3 == -1 && cvssV4 == -1; final double unscoredCvss = (useUnscored && v.getUnscoredSeverity() != null) ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1; - if (cvssV2 >= config.failBuildOnCVSS - || cvssV3 >= config.failBuildOnCVSS - || cvssV4 >= config.failBuildOnCVSS - || useUnscored && unscoredCvss >= config.failBuildOnCVSS + if (cvssV2 >= config.failBuildOnCVSS.get() + || cvssV3 >= config.failBuildOnCVSS.get() + || cvssV4 >= config.failBuildOnCVSS.get() + || useUnscored && unscoredCvss >= config.failBuildOnCVSS.get() //safety net to fail on any if for some reason the above misses on 0 - || (config.failBuildOnCVSS <= 0.0f)) { + || (config.failBuildOnCVSS.get() <= 0.0f)) { vulnerabilities.add(v.getName()); } } @@ -271,7 +271,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { if (vulnerabilities.size() > 0) { final String msg = String.format("%n%nDependency-Analyze Failure:%n" + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater than '%.1f': %s%n" - + "See the dependency-check report for more details.%n%n", config.failBuildOnCVSS, vulnerabilities.join(", ")) + + "See the dependency-check report for more details.%n%n", config.failBuildOnCVSS.get(), vulnerabilities.join(", ")) return CheckForFailureResult.createFailed(msg) } else { return CheckForFailureResult.createSuccess() @@ -311,7 +311,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic def shouldBeScanned(Project project) { - !config.scanProjects || config.scanProjects.contains(project.path) + config.scanProjects.get().isEmpty() || config.scanProjects.get().contains(project.path) } /** @@ -320,7 +320,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic def shouldBeSkipped(Project project) { - config.skipProjects.contains(project.path) + config.skipProjects.get().contains(project.path) } /** @@ -330,7 +330,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic boolean shouldBeScanned(Configuration configuration) { - !config.scanConfigurations || config.scanConfigurations.contains(configuration.name) + config.scanConfigurations.get().isEmpty() || config.scanConfigurations.get().contains(configuration.name) } /** @@ -345,7 +345,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { "runtime".equals(configuration.name) || "compile".equals(configuration.name) || "compileOnly".equals(configuration.name))) - || config.skipConfigurations.contains(configuration.name)) + || config.skipConfigurations.get().contains(configuration.name)) } /** @@ -355,7 +355,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { @groovy.transform.CompileStatic def shouldBeSkipped(ResolvedArtifactResult artifact) { def name = artifact.id.componentIdentifier.displayName - config.skipGroups.any { name.startsWith(it) } + config.skipGroups.get().any { name.startsWith(it) } } /** @@ -364,7 +364,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { */ @groovy.transform.CompileStatic boolean shouldBeSkippedAsTest(Configuration configuration) { - config.skipTestGroups && isTestConfiguration(configuration) + config.skipTestGroups.get() && isTestConfiguration(configuration) } /** @@ -470,12 +470,12 @@ abstract class AbstractAnalyze extends ConfiguredTask { config.additionalCpes.each { var dependency = new Dependency(true); - dependency.setDescription(it.description) - dependency.setDisplayFileName(it.cpe); - dependency.setSha1sum(Checksum.getSHA1Checksum(it.cpe)); - dependency.setSha256sum(Checksum.getSHA256Checksum(it.cpe)); - dependency.setMd5sum(Checksum.getMD5Checksum(it.cpe)); - dependency.addVulnerableSoftwareIdentifier(new CpeIdentifier(CpeParser.parse(it.cpe), Confidence.HIGHEST)) + dependency.setDescription(it.description.getOrNull()) + dependency.setDisplayFileName(it.cpe.getOrNull()); + dependency.setSha1sum(Checksum.getSHA1Checksum(it.cpe.getOrNull())); + dependency.setSha256sum(Checksum.getSHA256Checksum(it.cpe.getOrNull())); + dependency.setMd5sum(Checksum.getMD5Checksum(it.cpe.getOrNull())); + dependency.addVulnerableSoftwareIdentifier(new CpeIdentifier(CpeParser.parse(it.cpe.getOrNull()), Confidence.HIGHEST)) dependency.setFileName("") dependency.setActualFilePath("") engine.addDependency(dependency) @@ -579,7 +579,7 @@ abstract class AbstractAnalyze extends ConfiguredTask { } Map> includedByMap = buildIncludedByMap(project, configuration, scanningBuildEnv) - def types = config.analyzedTypes + def types = config.analyzedTypes.get() for (String type : types) { List rar = configuration.incoming.artifactView { lenient true diff --git a/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/ConfiguredTask.groovy b/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/ConfiguredTask.groovy index ea47d8a..6212ffe 100644 --- a/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/ConfiguredTask.groovy +++ b/src/main/groovy/org/owasp/dependencycheck/gradle/tasks/ConfiguredTask.groovy @@ -67,68 +67,68 @@ abstract class ConfiguredTask extends DefaultTask { } } } - settings.setBooleanIfNotNull(AUTO_UPDATE, config.autoUpdate) + settings.setBooleanIfNotNull(AUTO_UPDATE, config.autoUpdate.getOrNull()) - String[] suppressionLists = determineSuppressions(config.suppressionFiles, config.suppressionFile) + String[] suppressionLists = determineSuppressions(config.suppressionFiles.getOrElse([]), config.suppressionFile.getOrNull()) settings.setArrayIfNotEmpty(SUPPRESSION_FILE, suppressionLists) - settings.setStringIfNotEmpty(SUPPRESSION_FILE_USER, config.suppressionFileUser) - settings.setStringIfNotEmpty(SUPPRESSION_FILE_PASSWORD, config.suppressionFilePassword) - settings.setStringIfNotEmpty(SUPPRESSION_FILE_BEARER_TOKEN, config.suppressionFileBearerToken) - settings.setStringIfNotEmpty(HINTS_FILE, config.hintsFile) + settings.setStringIfNotEmpty(SUPPRESSION_FILE_USER, config.suppressionFileUser.getOrNull()) + settings.setStringIfNotEmpty(SUPPRESSION_FILE_PASSWORD, config.suppressionFilePassword.getOrNull()) + settings.setStringIfNotEmpty(SUPPRESSION_FILE_BEARER_TOKEN, config.suppressionFileBearerToken.getOrNull()) + settings.setStringIfNotEmpty(HINTS_FILE, config.hintsFile.getOrNull()) configureProxy(settings) configureSlack(settings) //settings.setStringIfNotEmpty(CONNECTION_TIMEOUT, connectionTimeout) - settings.setStringIfNotNull(DATA_DIRECTORY, config.data.directory) - settings.setStringIfNotEmpty(DB_DRIVER_NAME, config.data.driver) - settings.setStringIfNotEmpty(DB_DRIVER_PATH, config.data.driverPath) - settings.setStringIfNotEmpty(DB_CONNECTION_STRING, config.data.connectionString) - settings.setStringIfNotEmpty(DB_USER, config.data.username) - settings.setStringIfNotEmpty(DB_PASSWORD, config.data.password) + settings.setStringIfNotNull(DATA_DIRECTORY, config.data.directory.getOrNull()) + settings.setStringIfNotEmpty(DB_DRIVER_NAME, config.data.driver.getOrNull()) + settings.setStringIfNotEmpty(DB_DRIVER_PATH, config.data.driverPath.getOrNull()) + settings.setStringIfNotEmpty(DB_CONNECTION_STRING, config.data.connectionString.getOrNull()) + settings.setStringIfNotEmpty(DB_USER, config.data.username.getOrNull()) + settings.setStringIfNotEmpty(DB_PASSWORD, config.data.password.getOrNull()) - settings.setStringIfNotEmpty(NVD_API_KEY, config.nvd.apiKey) - settings.setStringIfNotEmpty(NVD_API_ENDPOINT, config.nvd.endpoint) - settings.setIntIfNotNull(NVD_API_DELAY, config.nvd.delay) - settings.setIntIfNotNull(NVD_API_RESULTS_PER_PAGE, config.nvd.resultsPerPage) - settings.setIntIfNotNull(NVD_API_MAX_RETRY_COUNT, config.nvd.maxRetryCount) - settings.setIntIfNotNull(NVD_API_VALID_FOR_HOURS, config.nvd.validForHours); + settings.setStringIfNotEmpty(NVD_API_KEY, config.nvd.apiKey.getOrNull()) + settings.setStringIfNotEmpty(NVD_API_ENDPOINT, config.nvd.endpoint.getOrNull()) + settings.setIntIfNotNull(NVD_API_DELAY, config.nvd.delay.getOrNull()) + settings.setIntIfNotNull(NVD_API_RESULTS_PER_PAGE, config.nvd.resultsPerPage.getOrNull()) + settings.setIntIfNotNull(NVD_API_MAX_RETRY_COUNT, config.nvd.maxRetryCount.getOrNull()) + settings.setIntIfNotNull(NVD_API_VALID_FOR_HOURS, config.nvd.validForHours.getOrNull()); - settings.setStringIfNotEmpty(NVD_API_DATAFEED_URL, config.nvd.datafeedUrl) - if (config.nvd.datafeedUser && config.nvd.datafeedPassword) { - settings.setStringIfNotEmpty(NVD_API_DATAFEED_USER, config.nvd.datafeedUser) - settings.setStringIfNotEmpty(NVD_API_DATAFEED_PASSWORD, config.nvd.datafeedPassword) + settings.setStringIfNotEmpty(NVD_API_DATAFEED_URL, config.nvd.datafeedUrl.getOrNull()) + if (config.nvd.datafeedUser.getOrNull() && config.nvd.datafeedPassword.getOrNull()) { + settings.setStringIfNotEmpty(NVD_API_DATAFEED_USER, config.nvd.datafeedUser.getOrNull()) + settings.setStringIfNotEmpty(NVD_API_DATAFEED_PASSWORD, config.nvd.datafeedPassword.getOrNull()) } - settings.setStringIfNotEmpty(NVD_API_DATAFEED_BEARER_TOKEN, config.nvd.datafeedBearerToken) - settings.setIntIfNotNull(NVD_API_DATAFEED_START_YEAR, config.nvd.datafeedStartYear) + settings.setStringIfNotEmpty(NVD_API_DATAFEED_BEARER_TOKEN, config.nvd.datafeedBearerToken.getOrNull()) + settings.setIntIfNotNull(NVD_API_DATAFEED_START_YEAR, config.nvd.datafeedStartYear.getOrNull()) - settings.setBooleanIfNotNull(DOWNLOADER_QUICK_QUERY_TIMESTAMP, config.quickQueryTimestamp) - settings.setFloat(JUNIT_FAIL_ON_CVSS, config.junitFailOnCVSS) - settings.setBooleanIfNotNull(FAIL_ON_UNUSED_SUPPRESSION_RULE, config.failBuildOnUnusedSuppressionRule) - settings.setBooleanIfNotNull(HOSTED_SUPPRESSIONS_ENABLED, config.hostedSuppressions.enabled) - settings.setBooleanIfNotNull(HOSTED_SUPPRESSIONS_FORCEUPDATE, config.hostedSuppressions.forceupdate) - settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_URL, config.hostedSuppressions.url) - settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_USER, config.hostedSuppressions.user) - settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_PASSWORD, config.hostedSuppressions.password) - settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_BEARER_TOKEN, config.hostedSuppressions.bearerToken) - if (config.hostedSuppressions.validForHours != null) { - if (config.hostedSuppressions.validForHours >= 0) { - settings.setInt(HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, config.hostedSuppressions.validForHours) + settings.setBooleanIfNotNull(DOWNLOADER_QUICK_QUERY_TIMESTAMP, config.quickQueryTimestamp.getOrNull()) + settings.setFloat(JUNIT_FAIL_ON_CVSS, config.junitFailOnCVSS.get()) + settings.setBooleanIfNotNull(FAIL_ON_UNUSED_SUPPRESSION_RULE, config.failBuildOnUnusedSuppressionRule.getOrNull()) + settings.setBooleanIfNotNull(HOSTED_SUPPRESSIONS_ENABLED, config.hostedSuppressions.enabled.getOrNull()) + settings.setBooleanIfNotNull(HOSTED_SUPPRESSIONS_FORCEUPDATE, config.hostedSuppressions.forceupdate.getOrNull()) + settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_URL, config.hostedSuppressions.url.getOrNull()) + settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_USER, config.hostedSuppressions.user.getOrNull()) + settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_PASSWORD, config.hostedSuppressions.password.getOrNull()) + settings.setStringIfNotNull(HOSTED_SUPPRESSIONS_BEARER_TOKEN, config.hostedSuppressions.bearerToken.getOrNull()) + if (config.hostedSuppressions.validForHours.getOrNull() != null) { + if (config.hostedSuppressions.validForHours.getOrNull() >= 0) { + settings.setInt(HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, config.hostedSuppressions.validForHours.getOrNull()) } else { throw new InvalidUserDataException('Invalid setting: `validForHours` must be 0 or greater') } } settings.setBooleanIfNotNull(ANALYZER_JAR_ENABLED, config.analyzers.jarEnabled) settings.setBooleanIfNotNull(ANALYZER_NUSPEC_ENABLED, config.analyzers.nuspecEnabled) - settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_ENABLED, select(config.analyzers.ossIndex.enabled, config.analyzers.ossIndexEnabled)) - settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, config.analyzers.ossIndex.warnOnlyOnRemoteErrors) - settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_ENABLED, config.analyzers.ossIndex.enabled) - settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_USER, config.analyzers.ossIndex.username) - settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_PASSWORD, config.analyzers.ossIndex.password) - settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_URL, config.analyzers.ossIndex.url) + settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_ENABLED, select(config.analyzers.ossIndex.enabled.getOrNull(), config.analyzers.ossIndexEnabled)) + settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, config.analyzers.ossIndex.warnOnlyOnRemoteErrors.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_ENABLED, config.analyzers.ossIndex.enabled.getOrNull()) + settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_USER, config.analyzers.ossIndex.username.getOrNull()) + settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_PASSWORD, config.analyzers.ossIndex.password.getOrNull()) + settings.setStringIfNotEmpty(ANALYZER_OSSINDEX_URL, config.analyzers.ossIndex.url.getOrNull()) settings.setBooleanIfNotNull(ANALYZER_CENTRAL_ENABLED, config.analyzers.centralEnabled) @@ -138,12 +138,12 @@ abstract class ConfiguredTask extends DefaultTask { settings.setBooleanIfNotNull(ANALYZER_EXPERIMENTAL_ENABLED, config.analyzers.experimentalEnabled) settings.setBooleanIfNotNull(ANALYZER_ARCHIVE_ENABLED, config.analyzers.archiveEnabled) - settings.setBooleanIfNotNull(ANALYZER_KNOWN_EXPLOITED_ENABLED, config.analyzers.kev.enabled) - settings.setStringIfNotNull(KEV_URL, config.analyzers.kev.url) - settings.setIntIfNotNull(KEV_CHECK_VALID_FOR_HOURS, config.analyzers.kev.validForHours) - settings.setStringIfNotNull(KEV_USER, config.analyzers.kev.user) - settings.setStringIfNotNull(KEV_PASSWORD, config.analyzers.kev.password) - settings.setStringIfNotNull(KEV_BEARER_TOKEN, config.analyzers.kev.bearerToken) + settings.setBooleanIfNotNull(ANALYZER_KNOWN_EXPLOITED_ENABLED, config.analyzers.kev.enabled.getOrNull()) + settings.setStringIfNotNull(KEV_URL, config.analyzers.kev.url.getOrNull()) + settings.setIntIfNotNull(KEV_CHECK_VALID_FOR_HOURS, config.analyzers.kev.validForHours.getOrNull()) + settings.setStringIfNotNull(KEV_USER, config.analyzers.kev.user.getOrNull()) + settings.setStringIfNotNull(KEV_PASSWORD, config.analyzers.kev.password.getOrNull()) + settings.setStringIfNotNull(KEV_BEARER_TOKEN, config.analyzers.kev.bearerToken.getOrNull()) settings.setStringIfNotEmpty(ADDITIONAL_ZIP_EXTENSIONS, config.analyzers.zipExtensions) settings.setBooleanIfNotNull(ANALYZER_ASSEMBLY_ENABLED, config.analyzers.assemblyEnabled) settings.setBooleanIfNotNull(ANALYZER_MSBUILD_PROJECT_ENABLED, config.analyzers.msbuildEnabled) @@ -170,43 +170,43 @@ abstract class ConfiguredTask extends DefaultTask { settings.setBooleanIfNotNull(ANALYZER_CPANFILE_ENABLED, config.analyzers.cpanEnabled) settings.setBooleanIfNotNull(ANALYZER_NUGETCONF_ENABLED, config.analyzers.nugetconfEnabled) - settings.setBooleanIfNotNull(ANALYZER_NODE_PACKAGE_ENABLED, select(config.analyzers.nodePackage.enabled, config.analyzers.nodeEnabled)) - settings.setBooleanIfNotNull(ANALYZER_NODE_PACKAGE_SKIPDEV, config.analyzers.nodePackage.skipDevDependencies) - settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_ENABLED, select(config.analyzers.nodeAudit.enabled, config.analyzers.nodeAuditEnabled)) - settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_USE_CACHE, config.analyzers.nodeAudit.useCache) - settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_SKIPDEV, config.analyzers.nodeAudit.skipDevDependencies) - settings.setStringIfNotEmpty(ANALYZER_NODE_AUDIT_URL, config.analyzers.nodeAudit.url) - settings.setBooleanIfNotNull(ANALYZER_YARN_AUDIT_ENABLED, config.analyzers.nodeAudit.yarnEnabled) - settings.setStringIfNotNull(ANALYZER_YARN_PATH, config.analyzers.nodeAudit.yarnPath); - settings.setBooleanIfNotNull(ANALYZER_PNPM_AUDIT_ENABLED, config.analyzers.nodeAudit.pnpmEnabled) - settings.setStringIfNotNull(ANALYZER_PNPM_PATH, config.analyzers.nodeAudit.pnpmPath); - settings.setBooleanIfNotNull(ANALYZER_RETIREJS_ENABLED, config.analyzers.retirejs.enabled) - settings.setBooleanIfNotNull(ANALYZER_RETIREJS_FORCEUPDATE, config.analyzers.retirejs.forceupdate) - settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_URL, config.analyzers.retirejs.retireJsUrl) - settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_USER, config.analyzers.retirejs.user) - settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_PASSWORD, config.analyzers.retirejs.password) - settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_BEARER_TOKEN, config.analyzers.retirejs.bearerToken) - settings.setBooleanIfNotNull(ANALYZER_RETIREJS_FILTER_NON_VULNERABLE, config.analyzers.retirejs.filterNonVulnerable) - settings.setArrayIfNotEmpty(ANALYZER_RETIREJS_FILTERS, config.analyzers.retirejs.filters) + settings.setBooleanIfNotNull(ANALYZER_NODE_PACKAGE_ENABLED, select(config.analyzers.nodePackage.enabled.getOrNull(), config.analyzers.nodeEnabled)) + settings.setBooleanIfNotNull(ANALYZER_NODE_PACKAGE_SKIPDEV, config.analyzers.nodePackage.skipDevDependencies.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_ENABLED, select(config.analyzers.nodeAudit.enabled.getOrNull(), config.analyzers.nodeAuditEnabled)) + settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_USE_CACHE, config.analyzers.nodeAudit.useCache.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_SKIPDEV, config.analyzers.nodeAudit.skipDevDependencies.getOrNull()) + settings.setStringIfNotEmpty(ANALYZER_NODE_AUDIT_URL, config.analyzers.nodeAudit.url.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_YARN_AUDIT_ENABLED, config.analyzers.nodeAudit.yarnEnabled.getOrNull()) + settings.setStringIfNotNull(ANALYZER_YARN_PATH, config.analyzers.nodeAudit.yarnPath.getOrNull()); + settings.setBooleanIfNotNull(ANALYZER_PNPM_AUDIT_ENABLED, config.analyzers.nodeAudit.pnpmEnabled.getOrNull()) + settings.setStringIfNotNull(ANALYZER_PNPM_PATH, config.analyzers.nodeAudit.pnpmPath.getOrNull()); + settings.setBooleanIfNotNull(ANALYZER_RETIREJS_ENABLED, config.analyzers.retirejs.enabled.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_RETIREJS_FORCEUPDATE, config.analyzers.retirejs.forceupdate.getOrNull()) + settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_URL, config.analyzers.retirejs.retireJsUrl.getOrNull()) + settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_USER, config.analyzers.retirejs.user.getOrNull()) + settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_PASSWORD, config.analyzers.retirejs.password.getOrNull()) + settings.setStringIfNotNull(ANALYZER_RETIREJS_REPO_JS_BEARER_TOKEN, config.analyzers.retirejs.bearerToken.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_RETIREJS_FILTER_NON_VULNERABLE, config.analyzers.retirejs.filterNonVulnerable.getOrNull()) + settings.setArrayIfNotEmpty(ANALYZER_RETIREJS_FILTERS, config.analyzers.retirejs.filters.getOrElse([])) - settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_ENABLED, config.analyzers.artifactory.enabled) - settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_PARALLEL_ANALYSIS, config.analyzers.artifactory.parallelAnalysis) - settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_USES_PROXY, config.analyzers.artifactory.usesProxy) - settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_URL, config.analyzers.artifactory.url) - settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_API_TOKEN, config.analyzers.artifactory.apiToken) - settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_API_USERNAME, config.analyzers.artifactory.username) - settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_BEARER_TOKEN, config.analyzers.artifactory.bearerToken) + settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_ENABLED, config.analyzers.artifactory.enabled.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_PARALLEL_ANALYSIS, config.analyzers.artifactory.parallelAnalysis.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_ARTIFACTORY_USES_PROXY, config.analyzers.artifactory.usesProxy.getOrNull()) + settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_URL, config.analyzers.artifactory.url.getOrNull()) + settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_API_TOKEN, config.analyzers.artifactory.apiToken.getOrNull()) + settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_API_USERNAME, config.analyzers.artifactory.username.getOrNull()) + settings.setStringIfNotNull(ANALYZER_ARTIFACTORY_BEARER_TOKEN, config.analyzers.artifactory.bearerToken.getOrNull()) - settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_USE_CACHE, config.cache.nodeAudit) - settings.setBooleanIfNotNull(ANALYZER_CENTRAL_USE_CACHE, config.cache.central) - settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_USE_CACHE, config.cache.ossIndex) + settings.setBooleanIfNotNull(ANALYZER_NODE_AUDIT_USE_CACHE, config.cache.nodeAudit.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_CENTRAL_USE_CACHE, config.cache.central.getOrNull()) + settings.setBooleanIfNotNull(ANALYZER_OSSINDEX_USE_CACHE, config.cache.ossIndex.getOrNull()) Downloader.getInstance().configure(settings); } private void configureSlack(Settings settings) { - settings.setBooleanIfNotNull(SlackNotificationSenderService.SLACK__WEBHOOK__ENABLED, config.slack.enabled) - settings.setStringIfNotEmpty(SlackNotificationSenderService.SLACK__WEBHOOK__URL, config.slack.webhookUrl) + settings.setBooleanIfNotNull(SlackNotificationSenderService.SLACK__WEBHOOK__ENABLED, config.slack.enabled.getOrNull()) + settings.setStringIfNotEmpty(SlackNotificationSenderService.SLACK__WEBHOOK__URL, config.slack.webhookUrl.getOrNull()) } private void configureProxy(Settings settings) { @@ -216,27 +216,28 @@ abstract class ConfiguredTask extends DefaultTask { String nonProxyHosts = System.getProperty("https.nonProxyHosts", System.getProperty("http.nonProxyHosts")) String proxyUser = System.getProperty("https.proxyUser", System.getProperty("http.proxyUser")) String proxyPassword = System.getProperty("https.proxyPassword", System.getProperty("http.proxyPassword")) - config.proxy.server = proxyHost + config.proxy.server.set(proxyHost) try { - config.proxy.port = Integer.parseInt(proxyPort) + config.proxy.port.set(Integer.parseInt(proxyPort)) } catch (NumberFormatException nfe) { logger.warn("Unable to convert the configured `http.proxyPort` to a number: ${proxyPort}"); } if (!Strings.isNullOrEmpty(proxyUser)) { - config.proxy.username = proxyUser + config.proxy.username.set(proxyUser) } if (!Strings.isNullOrEmpty(proxyPassword)) { - config.proxy.password = proxyPassword + config.proxy.password.set(proxyPassword) } if (!Strings.isNullOrEmpty(nonProxyHosts)) { - config.proxy.nonProxyHosts = nonProxyHosts.tokenize("|") + config.proxy.nonProxyHosts.set(nonProxyHosts.tokenize("|")) } } - settings.setStringIfNotEmpty(PROXY_SERVER, config.proxy.server) - settings.setStringIfNotEmpty(PROXY_PORT, "${config.proxy.port}") - settings.setStringIfNotEmpty(PROXY_USERNAME, config.proxy.username) - settings.setStringIfNotEmpty(PROXY_PASSWORD, config.proxy.password) - settings.setStringIfNotEmpty(PROXY_NON_PROXY_HOSTS, config.proxy.nonProxyHosts.join("|")) + settings.setStringIfNotEmpty(PROXY_SERVER, config.proxy.server.getOrNull()) + settings.setStringIfNotEmpty(PROXY_PORT, config.proxy.port.getOrNull()?.toString()) + settings.setStringIfNotEmpty(PROXY_USERNAME, config.proxy.username.getOrNull()) + settings.setStringIfNotEmpty(PROXY_PASSWORD, config.proxy.password.getOrNull()) + def nonProxyHostsList = config.proxy.nonProxyHosts.getOrElse([]) + settings.setStringIfNotEmpty(PROXY_NON_PROXY_HOSTS, nonProxyHostsList ? nonProxyHostsList.join("|") : null) } /** diff --git a/src/test/groovy/org/owasp/dependencycheck/gradle/DependencyCheckGradlePluginSpec.groovy b/src/test/groovy/org/owasp/dependencycheck/gradle/DependencyCheckGradlePluginSpec.groovy index 9e6a966..959aee6 100644 --- a/src/test/groovy/org/owasp/dependencycheck/gradle/DependencyCheckGradlePluginSpec.groovy +++ b/src/test/groovy/org/owasp/dependencycheck/gradle/DependencyCheckGradlePluginSpec.groovy @@ -43,7 +43,7 @@ class DependencyCheckGradlePluginSpec extends Specification { DependencyCheckExtension extension = project.extensions.findByName('dependencyCheck') as DependencyCheckExtension expect: - extension.data.directory == "${project.gradle.gradleUserHomeDir}/dependency-check-data/11.0" + extension.data.directory.get() == "${project.gradle.gradleUserHomeDir}/dependency-check-data/11.0" } def "dependencyCheckAnalyze task exists"() { @@ -74,22 +74,22 @@ class DependencyCheckGradlePluginSpec extends Specification { task.group == 'OWASP dependency-check' task.description == 'Identifies and reports known vulnerabilities (CVEs) in project dependencies.' - project.dependencyCheck.proxy.server == null - project.dependencyCheck.proxy.port == null - project.dependencyCheck.proxy.username == null - project.dependencyCheck.proxy.password == null - project.dependencyCheck.nvd.apiKey == null - project.dependencyCheck.nvd.delay == null - project.dependencyCheck.nvd.maxRetryCount == null - project.dependencyCheck.outputDirectory == "${project.buildDir}/reports" - project.dependencyCheck.quickQueryTimestamp == null - project.dependencyCheck.scanConfigurations == [] - project.dependencyCheck.skipConfigurations == [] - project.dependencyCheck.scanProjects == [] - project.dependencyCheck.skipProjects == [] - project.dependencyCheck.skipGroups == [] - project.dependencyCheck.skipTestGroups == true - project.dependencyCheck.suppressionFile == null + project.dependencyCheck.proxy.server.getOrNull() == null + project.dependencyCheck.proxy.port.getOrNull() == null + project.dependencyCheck.proxy.username.getOrNull() == null + project.dependencyCheck.proxy.password.getOrNull() == null + project.dependencyCheck.nvd.apiKey.getOrNull() == null + project.dependencyCheck.nvd.delay.getOrNull() == null + project.dependencyCheck.nvd.maxRetryCount.getOrNull() == null + project.dependencyCheck.outputDirectory.get().asFile == project.file("${project.buildDir}/reports") + project.dependencyCheck.quickQueryTimestamp.getOrNull() == null + project.dependencyCheck.scanConfigurations.get() == [] + project.dependencyCheck.skipConfigurations.get() == [] + project.dependencyCheck.scanProjects.get() == [] + project.dependencyCheck.skipProjects.get() == [] + project.dependencyCheck.skipGroups.get() == [] + project.dependencyCheck.skipTestGroups.get() == true + project.dependencyCheck.suppressionFile.getOrNull() == null } def 'tasks use correct values when extension is used'() { @@ -157,44 +157,44 @@ class DependencyCheckGradlePluginSpec extends Specification { } then: - project.dependencyCheck.proxy.server == '127.0.0.1' - project.dependencyCheck.proxy.port == 3128 - project.dependencyCheck.proxy.username == 'proxyUsername' - project.dependencyCheck.proxy.password == 'proxyPassword' - project.dependencyCheck.proxy.nonProxyHosts == ['localhost'] - - project.dependencyCheck.nvd.apiKey == 'apiKey' - project.dependencyCheck.nvd.delay == 5000 - project.dependencyCheck.nvd.maxRetryCount == 20 - project.dependencyCheck.hostedSuppressions.url == 'suppressionsurl' - project.dependencyCheck.hostedSuppressions.validForHours == 5 - project.dependencyCheck.hostedSuppressions.forceupdate == true - project.dependencyCheck.outputDirectory == 'outputDirectory' - project.dependencyCheck.quickQueryTimestamp == false - project.dependencyCheck.scanConfigurations == ['a'] - project.dependencyCheck.skipConfigurations == ['b'] - project.dependencyCheck.scanProjects == ['a'] - project.dependencyCheck.skipProjects == ['b'] - project.dependencyCheck.skipGroups == ['b'] - project.dependencyCheck.skipTestGroups == false - project.dependencyCheck.suppressionFile == './src/config/suppression.xml' - project.dependencyCheck.suppressionFiles.getAt(0) == './src/config/suppression1.xml' - project.dependencyCheck.suppressionFiles.getAt(1) == './src/config/suppression2.xml' + project.dependencyCheck.proxy.server.get() == '127.0.0.1' + project.dependencyCheck.proxy.port.get() == 3128 + project.dependencyCheck.proxy.username.get() == 'proxyUsername' + project.dependencyCheck.proxy.password.get() == 'proxyPassword' + project.dependencyCheck.proxy.nonProxyHosts.get() == ['localhost'] + + project.dependencyCheck.nvd.apiKey.get() == 'apiKey' + project.dependencyCheck.nvd.delay.get() == 5000 + project.dependencyCheck.nvd.maxRetryCount.get() == 20 + project.dependencyCheck.hostedSuppressions.url.get() == 'suppressionsurl' + project.dependencyCheck.hostedSuppressions.validForHours.get() == 5 + project.dependencyCheck.hostedSuppressions.forceupdate.get() == true + project.dependencyCheck.outputDirectory.get().asFile == project.file('outputDirectory') + project.dependencyCheck.quickQueryTimestamp.get() == false + project.dependencyCheck.scanConfigurations.get() == ['a'] + project.dependencyCheck.skipConfigurations.get() == ['b'] + project.dependencyCheck.scanProjects.get() == ['a'] + project.dependencyCheck.skipProjects.get() == ['b'] + project.dependencyCheck.skipGroups.get() == ['b'] + project.dependencyCheck.skipTestGroups.get() == false + project.dependencyCheck.suppressionFile.get() == './src/config/suppression.xml' + project.dependencyCheck.suppressionFiles.get().getAt(0) == './src/config/suppression1.xml' + project.dependencyCheck.suppressionFiles.get().getAt(1) == './src/config/suppression2.xml' //project.dependencyCheck.suppressionFiles == ['./src/config/suppression1.xml', './src/config/suppression2.xml'] - project.dependencyCheck.suppressionFileUser == 'suppressionFileUsername' - project.dependencyCheck.suppressionFilePassword == 'suppressionFilePassword' - project.dependencyCheck.analyzers.artifactory.enabled == true - project.dependencyCheck.analyzers.artifactory.url == 'https://example.com/artifacgtory' - project.dependencyCheck.analyzers.artifactory.bearerToken == 'abc123==' - project.dependencyCheck.analyzers.kev.enabled == false - project.dependencyCheck.analyzers.kev.url == "https://example.com" - project.dependencyCheck.analyzers.retirejs.filters == ['filter1', 'filter2'] - project.dependencyCheck.analyzers.retirejs.filterNonVulnerable == true - project.dependencyCheck.slack.enabled == true - project.dependencyCheck.slack.webhookUrl == slackWebhookUrl + project.dependencyCheck.suppressionFileUser.get() == 'suppressionFileUsername' + project.dependencyCheck.suppressionFilePassword.get() == 'suppressionFilePassword' + project.dependencyCheck.analyzers.artifactory.enabled.get() == true + project.dependencyCheck.analyzers.artifactory.url.get() == 'https://example.com/artifacgtory' + project.dependencyCheck.analyzers.artifactory.bearerToken.get() == 'abc123==' + project.dependencyCheck.analyzers.kev.enabled.get() == false + project.dependencyCheck.analyzers.kev.url.get() == "https://example.com" + project.dependencyCheck.analyzers.retirejs.filters.get() == ['filter1', 'filter2'] + project.dependencyCheck.analyzers.retirejs.filterNonVulnerable.get() == true + project.dependencyCheck.slack.enabled.get() == true + project.dependencyCheck.slack.webhookUrl.get() == slackWebhookUrl project.dependencyCheck.additionalCpes.size() == 3 - project.dependencyCheck.additionalCpes.getByName('additional1').description == 'Additional1' - project.dependencyCheck.additionalCpes.getByName('additional1').cpe == 'cpe:2.3:a:aGroup1:aPackage1:123:*:*:*:*:*:*:*' + project.dependencyCheck.additionalCpes.getByName('additional1').description.get() == 'Additional1' + project.dependencyCheck.additionalCpes.getByName('additional1').cpe.get() == 'cpe:2.3:a:aGroup1:aPackage1:123:*:*:*:*:*:*:*' }