Introduction
The JarEnforcer is a Maven Enforcer that, subject to configuration, performs the following tests on a distribution's externally-provided (dependency) jars.
Tests that they are signed by a key which is in an appropriate keyRing, failing if any signatures are missing or not resolvable.
Tests that the version is the one specified in the pom file (because maven’s resolution of dependencies is non intuitive). This fails if versions mismatch, or if artifacts are missing.
As a part of this test it can also do a reverse lookup and provide a trace back to which pom-specified artifact caused a particular jar to become a part of the distribution
Finally it can check the signature of every jar in your local maven repository. This can be used to check for supply chain attacks via maven plugins.
Configuration
This is done by adding the following stanza to the pom file for the project distribution.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <dependencies> <dependency> <groupId>net.shibboleth.maven.enforcer.rules</groupId> <artifactId>maven-dist-enforcer</artifactId> <version>2.1.0</version> </dependency> </dependencies> <executions> <execution> <id>idp-enforce</id> <phase>verify</phase> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <jarEnforcer implementation="net.shibboleth.mvn.enforcer.impl.JarEnforcer"> <enforcerData>${basedir}/src/main/enforcer</enforcerData> <parentPomDir>${basedir}/../idp-parent</parentPomDir> <jarDirs>${project.build.directory}/${idp.finalName}/bin/lib ${project.build.directory}/${idp.finalName}/webapp/WEB-INF/lib</jarDirs> <checkSignatures>true</checkSignatures> <checkDependencies>true</checkDependencies> <listJarSources>true</listJarSources> <artifactMap>${basedir}/src/main/enforcer/artifactMap.properties</artifactMap> </jarEnforcer> </rules> </configuration> </execution> </executions> </plugin>
The supported parameters are:
Element Name | Required? | Default | Function |
---|---|---|---|
parentPomDir | Yes | This is the absolute path to the directory where the parent pom for the project is stored. This is parsed and used to
| |
dataGroupId 3.0 | Yes | Maven coordinates of the project which contains the keys (and if required) signatures for jars. See below. Supercedes enforcerData | |
dataKeyRing 3.0 | Yes | Absolute path to a keyring with keys which will be used to check the validity of the above specified jar file | |
tgzFiles 3.0 | One must be present | Space separated list of tar.gz files to be scanned. Supercedes jarFiles | |
zipFiles 3.0 | Space separated list of zip files to be scanned. Supercedes jarFiles | ||
checkSignatures | true | Whether to run signature checking on the contents | |
sigCheckReportPath 3.0 | ${project.build.directory}\signatureReport.txt | Where to write the report of the signature checking | |
checkDependencies | true | Whether to run dependency analysis and report if any versions mismatch | |
listJarSources | false | Whether, as part of the dependency check to do a reverse look up of artifact to source (this is a slow operation) | |
depCheckReportPath 3.0 | ${project.build.directory}\dependencyReport.txt | Where to write the report of the signature checking | |
checkM2 | false | Whether all the non-source, non-test jar files in the users maven repository (~/.m2/repository) will be checked | |
m2ReportPath 3.0 | ${project.build.directory}\m2SignatureReport.txt | Where to write the report of the m2 checking |
The Enforcer Data jar
The jar file referenced by the dataGroupId/dataArtifactId/dataVersion coordinated contains three sets of data used by the enforcer. These are all contained below the net/shibboleth/mvn/enforcer/data/
directory.
A file called
artifactMap.properties
which contains the mapping from artifactid to group. This is used where jar files are encountered which are not explicitly mentioned in the parent pomA directory called
localsignatures
which contains a series of files whose name is of the formartifactId-version.jar.asc
(e.g.antlr-2.7.7.jar.asc
) these being signatures on the respective jar files. This is a fallback for when jar files have been publish with no signature. Such signatures should only be added if the jar file has had independend verificationA directory called
keyRing
which contains a series off keyrings and which is described below.
Configuring keyRings
Signature checking is done against a series of (GPG) keyrings in the net/shibboleth/mvn/enforcer/data/keyRings
subdirectory of the jar specified by the dataXXX
maven coordinates in V3 and the enforcerData
path in V2.
Each keyring contains all the public keys which are trusted to validate the signatures of all artifacts with that groupId. The name of each key ring is the groupId with suffix .gpg
. As an interim step in keyring deployment it is possible to supply an .asc
file with the name derived soley from the groupId (with no suffix).
These keyrings require maintenance:
If an artifact is added to the distribution and it is not signed with a trusted key
If the version of an artifact changed and the signature on it is not a trusted key.
In both this cases the artifact will not have been added to our repository without a signature check and so it is an absolute assumption that the public key is available.
Adding a new artifact
If an artifact is added implicitly as a dependency then you may need to add the artifactId to groupId mapping to the artifactMap.
If the artifact is in a previously unknown groupId then you must create an empty GPG keyring with the appropriate name (and empty keyring is an empty file with a
.gpg
extension
Adding a new public key to a keyring
Only commit a change to the keyring after discussion with the committers group (either by Slack or by email) to ensure that an appropriate process has been followed for accrediting the signatory.
Assuming that the key is help in a file called pubkey.asc
and the groupId is the.maven.group
the following command will add the key.
gpg --no-default-keyring --keyring ./the.maven.group.gpg --import pubkey.asc rm ./the.maven.group.bak rm ./the.maven.group.gpg.lock git add ./the.maven.group.gpg