Optimized Component Lifecycle Management with Sonatype CLM

5.5. Sonatype CLM Maven Plugin

5.5.1. CLM Maven Plugin Introduction

A Sonatype CLM evaluation of a Maven based software project can be assisted by the Sonatype CLM Maven plugin. It can take advantage of the dependency information contained in the project’s pom.xml files and the information about transitive dependencies available to Maven. It can be run on a command line interface and can therefore be executed on any continuous integration server.

When using the plugin on a multi-module project in most cases you will only configure an execution for the modules that produce components that will be deployed as an application. Typically these are ear files or war files for deployment on application servers or tar.gz or other archives that are used for production deployments or distribution to users. However you can also analyze a all modules of a project. This will largely depend on what your CLM policy is enforcing and what you want to validate.

The index goal of the plugin allows you to prepare data for analysis with Sonatype CLM for CI.

The attach goal aids your integration with Sonatype Nexus CLM Edition and the release process using the staging tools of Nexus.

The evaluate goal can trigger an evaluation directly against a Sonatype CLM server.

The help goal provides documentation for all the goals and parameters and you can invoke it with an execution like

mvn com.sonatype.clm:clm-maven-plugin:2.1.1:help

The following sections detail a these goals and their usage.

5.5.2. Creating a Component Index for Sonatype CLM for CI

The index goal of the CLM Maven plugin allows you to identify component dependencies and makes this information available to the Sonatype CLM for CI plugin. You can invoke an execution of the index goal manually as part of your command line invocation by executing the index goal after the package phase:

mvn clean install com.sonatype.clm:clm-maven-plugin:index

Alternatively you can configure the execution in the pom.xml files build section or in a profile's build section.

 <build>
    <plugins>
      <plugin>
        <groupId>com.sonatype.clm</groupId>
        <artifactId>clm-maven-plugin</artifactId>
        <version>2.1.1</version>
        <executions>
          <execution>
            <goals>
            <goal>index</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

With the above configuration a normal Maven build execution with e.g. mvn clean install will trigger the CLM plugin to be executed in the package phase and result in a log output similar to

[INFO] --- clm-maven-plugin:2.1.1:index (default) @ test-app ---
[INFO] Saved module information to /opt/test-app/target/sonatype-clm/module.xml

If you want to manually configure the lifecycle phase to execute the plugin, you have to choose a phase after package.

The generated module.xml file contains the information that will be picked up by Sonatype CLM for CI and incorporated into the CLM evaluation. This improves the analysis since the CLM Maven plugin is able to create a complete dependency list rather than relying on binary build artifacts.

Only dependencies in the compile or runtime scopes will be considered, since this reflects what other Maven packaging plugins typically include. Dependencies with the scopes test, provided and system will not be considered.

5.5.3. Creating a Component Info Archive for Nexus Pro CLM Edition

The attach goal scans the dependencies and build artifacts of a project and attaches the results to the project as another artifact in the form of a scan.xml.gz file. It contains all the checksums for the dependencies and their classes and further meta information and can be found in the target/sonatype-clm directory. A separate scan.xml.gz file is generated for each maven module in an aggregator project in which the plugin is executed.

This attachment causes the file to be part of any Maven install and deploy invocation. When the deployment is executed against a Sonatype Nexus CLM Edition server the artifact is used to evaluate policies against the components included in the scan.

To use this goal, add an execution for it in the POM, e.g. as part of a profile used during releases:

 <build>
    <plugins>
      <plugin>
        <groupId>com.sonatype.clm</groupId>
        <artifactId>clm-maven-plugin</artifactId>
        <version>2.1.1</version>
        <executions>
          <execution>
            <goals>
            <goal>attach</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Once configured in your project, the build log will contain messages similar to

[INFO] --- clm-maven-plugin:2.1.1:attach (default) @ test-app ---
[INFO] Starting scan...
[INFO] Scanning ...plexus-utils-3.0.jar
[INFO] Scanning ...maven-settings-3.0.jar...
[INFO] Scanning target/test-app-1.0-SNAPSHOT.jar...
[INFO] Saved module scan to /opt/test-app/target/sonatype-clm/scan.xml.gz

The attachment of the scan.xml.gz file as a build artifact causes an it to be stored in the local repository as well as the deployment repository manager or the Nexus staging repository ending with -sonatype-clm-scan.xml.gz. This file will be picked up by Sonatype Nexus CLM Edition and used in the policy analysis during the staging process. It improves the analysis since the CLM Maven plugin is able to create a complete dependency list rather than relying on binary build artifacts.

5.5.4. Evaluating Project Components with Sonatype CLM Server

The evaluate goal scans the dependencies and build artifacts of a project and directly submits the information to a Sonatype CLM Server for policy evaluation.

If a policy violation is found and the CLM stage is configured to Fail, the Maven build will fail. If invoked for an aggregator project, dependencies of all child modules will be considered.

The evaluate goal requires the Sonatype CLM Server URL as well as the application identifier to be configured. Optionally a CLM stage can be configured.

The command line arguments are

clm.serverUrl
the URL for the CLM server, this parameter is required
clm.applicationId
the application identifier for the application to run policy against, this parameter is required
clm.resultFile

the path for specifying the location of a JSON file where the following information will be stored:

  • applicationId : Application ID
  • scanId : Organization ID
  • reportHtmlUrl : URL to the HTML version of the report
  • reportPdfUrl : URL to the PDF version of the report
  • reportDataUrl : URL to the Data version of the report (for use via CURL, or similar tool)
clm.stage
the stage to run policy against with the possible values of procure, develop, build, stage-release, release and operate with a default value of build.

An example invocation is:

mvn com.sonatype.clm:clm-maven-plugin:evaluate
-Dclm.applicationId=test -Dclm.serverUrl=http://localhost:8070

You can avoid specifying the parameters on the command line by adding them to your settings.xml or pom.xml as properties.

 <properties>
    <clm.serverUrl>http://localhost:8070</clm.serverUrl>
    <clm.applicationId>test</clm.applicationId>
 </properties>

Alternatively the invocation can be configured in a pom.xml file:

<build>
  <plugins>
    <plugin>
      <groupId>com.sonatype.clm</groupId>
      <artifactId>clm-maven-plugin</artifactId>
      <version>2.1.1</version>
      <executions>
        <execution>
          <goals>
            <goal>evaluate</goal>
          </goals>
          <phase>package</phase>
          <configuration>
            <serverUrl>http://localhost:8070</serverUrl>
            <stage>build</stage>
            <applicationId>test</applicationId>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

The CLM Maven plugin can be executed against an aggregator project. When executed in an aggregator project, it calculates the dependencies and transitive dependencies of all child modules and takes all of them into account for the policy evaluation. It advisable to set the inherited flag for the plugin to false to avoid duplicate runs of the plugin in each module.

Caution

When bound to a lifecycle in a multimodule build, the plugin will take all dependencies of the Maven reactor into consideration for its analysis and not just the dependencies of the current module.

The evaluate goal logs its activity and provides the location of the generated report.

[INFO] --- clm-maven-plugin:2.1.1:evaluate (default) @ test-app ---
[WARNING] Goal 'evaluate' is not expected to be used as part of project lifecycle.
[INFO] Starting scan...
[INFO] Scanning ../repository/org/codehaus/plexus/plexus-utils/3.0/plexus-utils-3.0.jar...
[INFO] Scanning ../repository/org/apache/maven/maven-settings/3.0/maven-settings-3.0.jar...
[INFO] Scanning target/test-app-1.0-SNAPSHOT.jar...
[INFO] Saved module scan to /opt/test-app/target/sonatype-clm/scan.xml.gz
[INFO] Uploading scan to http://localhost:8070 ...
[INFO] Evaluating policies... (ETA 5s)
[INFO] Policy Action: None
Summary of policy violations: 0 critical, 0 severe, 0 moderate
The detailed report can be viewed online at
http://localhost:8070/ui/links/application/test/report/f4582a1570634dc2ac8

After a successful build the report can be accessed in the Sonatype CLM server under the application that was configured. A direct link is provided on the log.

5.5.5. Simplifying Command Line Invocations

If you happen to use the plugin frequently by running it manually on the command line and want to shorten the command line even more, you can add a plugin group entry to your Maven settings.xml file:

 <settings>
   ...
   <pluginGroups>
     <pluginGroup>com.sonatype.clm</pluginGroup>
     ...
   </pluginGroups>
   ...
 </settings>

This enables you to invoke the plugin using its shorthand prefix form:

mvn ... clm:index

5.5.6. Skipping CLM Maven Plugin Executions

The clm.skip parameter can be used, when a CLM plugin execution is configured in your project’s pom.xml file, but you want to avoid the execution for a particular build. An example execution is

mvn clean install -Dclm.skip=true

The parameter can also be set in your IDE configuration for Maven build executions or as a property in your settings.xml or pom.xml:

 <properties>
    <clm.skip>true</clm.serverUrl>
 </properties>