Daily Archives: 2014-05-30

Enforce Dependency Management Policies with the Maven Dependency Plugin

A non-trivial application will typically rely on a multitude of libraries to provide basic functions. The complexity of such “dependencies” ranges anywhere from functions for basic datastructure manipulation to fully-featured socket server implementations. Much of this code is provided by third parties, and conveniently made available to build systems through large (public) repository servers like Maven Central.

In an application that is using these dependencies, third party code will ultimately handle user provided input. This opens up questions around security and policy compliance. As an example, an organization may want to ensure that dependencies with known security vulnerabilities are not being used in production code. There might also be dependencies that are only available under very restrictive license terms (e.g. GPL), and using them e.g. in a closed source product may be a policy violation. Further examples for policy violations may include governmental restrictions, such as export restrictions.

The Maven Dependency Plugin allows creating a project’s “dependency tree”, that is, a list of all direct and indirect (“transitive”) dependencies of a project. This tree can be stored in a text file for every module in a multi-module Maven build, and then be processed in a post-build step to scan, for example, for policy compliance of the presence / absence of specific versions of well-defined dependencies.

 

Specifying all dependencies in Maven’s DependencyManagement sections, preferably in a dedicated / high level (e.g. root) POM file ensures that all modules of a Maven project use the same version of a specific dependency. This greatly simplifies dependency management in a project, because there is no risk of contradicting dependency specifications. In particular when updating a dependency in a sub module, using Maven’s DependencyManagement sections makes it unnecessary to update that same dependency in a different (possible seldom changed) sub-module of the same project. Note that it is possible to have a DependencyManagement section in every PMO file, augmenting each other as the build progresses a project’s modules from the root to the leaves. This allows having multiple versions of the same dependency in a project if such a configuration would be required for valid reasons – and at the same time forces that such a decision is consciously made and explicitly documented in the POM files by creating appropriate entries in the various DependencyManagement sections.

 

The configuration example below shows how the Maven Dependency Plugin can be used to enforce that all dependency versions must be specified in a DependencyManagement section, and at the same time create a text file for each sub module with a fully qualified list (group ID, artifact ID, version, scope) of all direct and transitive module dependencies.

<build>
  ...
  <plugins>
    ...
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>${mavenDependencyPluginVersion}</version>
      <executions>
        <execution>
          <id>dep-resolve</id>
          <phase>validate</phase>
          <goals>
            <goal>resolve</goal>
          </goals>
          <configuration>
            <excludeTransitive>false</excludeTransitive>
            <outputFile>${project.build.directory}/dep_current.txt</outputFile>
          </configuration>
        </execution>
        <execution>
          <id>analyze-dep-mgt</id>
          <phase>validate</phase>
          <goals>
            <goal>analyze-dep-mgt</goal>
          </goals>
          <configuration>
            <failBuild>true</failBuild>
            <ignoreDirect>false</ignoreDirect>
          </configuration>
        </execution>
      </executions>
    </plugin>
    ...
  </plugins>
  ...
</build>

Edit:See https://github.com/mbeiter/util for an example on how to configure the Maven Dependency Plugin as described in this post for a multi-module build.