3个Maven插件确保质量和安全性


检测依赖项中的漏洞对于创建健壮、可靠和安全的应用程序至关重要。除此之外,静态代码分析工具和预定义规则可以帮助我们维护健康和定性的代码库。幸运的是,有 Maven 插件可用于在我们的构建中自动执行此操作。在这篇博文中,我将展示我最喜欢的三个 Maven 插件,以确保 Java 项目的质量和安全性。

Maven Enforcer器插件
Maven Enforcer 插件使我们能够检查项目的几个预定义规则。这可以像在构建期间检查 Java、Maven 或 OS 版本一样简单(在此处查找所有规则的列表)。

同样地,我们可以使用这个插件将一组被禁止进入我们项目的依赖关系列入黑名单。一个好的用例可能是在从JUnit 4过渡到JUnit 5之后。一旦我们所有的测试都使用JUnit 5,我们就可以排除JUnit 4的依赖,并创建一个规则,这样其他队友就不会再意外地包含它(并有可能混合JUnit 4和5,这是最常见的Spring Boot测试陷阱之一)。

接下来,我们可以使用Maven Enforcer插件中的dependencyConvergence规则,确保项目中只有一个版本的依赖。一旦我们的项目增加,包括更多的依赖,可能会有两个依赖拉入不同版本的Jackson,比如说。每当我们重新排列依赖关系、更新版本或删除依赖关系时,就会导致运行时出现问题(观看本视频,深入了解Maven如何处理依赖关系版本冲突)。

为了检测这种情况,只要有不同版本的横向依赖,dependencyConvergence规则就会失效。我们可以通过在依赖管理中钉住依赖版本或将其从一个依赖中排除,来解决这个问题。

我们将这个插件添加到我们的项目中,如下所示:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <configuration>
    <rules>
      <bannedDependencies>
        <excludes>
          <exclude>junit:junit</exclude>
          <exclude>junit:junit-dep</exclude>
        </excludes>
      </bannedDependencies>
      <dependencyConvergence/>
    </rules>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>enforce</goal>
      </goals>
    </execution>
  </executions>
</plugin>

一旦我们运行mvn verify或mvn enforcer:enforce,就会检查我们配置的规则。如果其中一条规则失败,我们的构建就会停止,Maven会报告构建失败。

OWASP依赖性检查以确保依赖性质量
我们在项目中添加的依赖关系越多,我们就越有可能处理共同漏洞和暴露(CVE)。手动检查CVE数据库中的新问题是很麻烦的。

幸运的是,有一个Maven插件可以在构建时完成这一工作:OWASP Dependency-Check Maven插件。该插件会分析我们所有的依赖关系,一旦我们的某个依赖关系是CVE的一部分,就会导致构建失败(如果配置了)或产生日志警告。

请注意,这些漏洞是从NIST主办的国家漏洞数据库(NVD)下载的:https://nvd.nist.gov。这在第一次运行时可能需要几分钟,如果我们计划使用它,我们肯定应该为我们的CI/CD管道启用缓存(GitHub Actions的例子在这里)。在过去,我们也观察到这个托管漏洞数据库的一些停机时间。在这种情况下,我们将该插件配置为不会使构建失败。

此外,可能有一些漏洞只发生在特定的依赖设置或操作系统上。为了抑制这种误报,我们可以在项目中添加一个 owasp-suppressions.xml 文件,排除这些 CVE:

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns=
"https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.2.xsd">
  <!-- example to suppress a false  warning
  <suppress>
      <notes><![CDATA[
       Suppress all dependencies for CVE-2018-1258 (https:
//pivotal.io/security/cve-2018-1258)
      ]]></notes>
      <cve>CVE-2018-1258</cve>
  </suppress>
   -->
</suppressions>

<plugin>
  <groupId>org.owasp</groupId>
  <artifactId>dependency-check-maven</artifactId>
  <version>7.1.1</version>
  <configuration>
    <suppressionFiles>
      <suppressionFile>${project.basedir}/owasp-suppressions.xml</suppressionFile>
    </suppressionFiles>
    <failBuildOnCVSS>8</failBuildOnCVSS>
    <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
    <failOnError>true</failOnError>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>check</goal>
      </goals>
    </execution>
  </executions>
</plugin>

通过 failBuildOnCVSS 配置值,我们指定一个 CVE 的严重程度,使构建失败。分数范围从0到10。

一旦我们运行mvn verify或mvn dependency-check:check,我们的依赖关系就会被分析出来。

SpotBugs Maven插件确保代码质量
拥有一个静态代码分析工具可能有助于修复潜在的错误。除了SonarQube,还有一个流行的Maven插件,不需要进一步设置:SpotBugs Maven插件(原名FindBugs)。

我们可以通过以下配置包含这个Maven插件:

<plugin>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>4.7.1.0</version>
  <executions>
    <execution>
      <goals>
        <goal>check</goal>
      </goals>
    </execution>
  </executions>
</plugin>

现在我们可以运行mvn spotbugs:check来分析我们的源代码。此外,我们可以用mvn spotbugs:gui启动一个简单的UI来分析潜在的代码分析警告。

在我们的例子中,SpotBugs抱怨了BadPracticeFileReader类的实现。它检测到三个潜在的错误,因为我们在从字节数组中创建字符串时使用了默认的编码,并且没有正确地清理打开的资源。

拥有一个静态分析工具是在早期发现低级错误的好方法。对于更复杂的代码分析,可以看看 SonarCloud。对于即时反馈,还有SonarLint,一个免费的IntelliJ IDEA插件。

案例源码:  GitHub.