0

i'm in the process of evaluating maven for building a company software. The special case i have is that all artifacts that are allowed to be used in production are restricted.

The approved libraries are maintained i a special repositoy (in a Artifactory instance).

While the final product is restricted we may use more dependencies for building (maven plugins and their dependencies have lesser restrictions).

So i configured the repository section in the pom and the pluginRepository.

The problem is now that all resolved artifacts (for the plugins and for the project) are cached in only one local repository/folder. If someone accidently adds a compile dependency to any of the projects that is only in the cache because of a maven-plugin it will be used without any warning.

I deleted the local repository and recompiled the tested project and the build failed as expected with a unresolveable dependency.

I've searched the web and didn't find a specific answer to this question. There is a pending request on maven to separate the local caches for each repository, but that seems to be only in reviewed for maven 4 state: https://cwiki.apache.org/confluence/display/MAVEN/Local+Repository+Separation

https://issues.apache.org/jira/browse/MNG-3655 https://issues.apache.org/jira/browse/MNG-4302

The maven-enforcer-plugin has kind of a concept here with bannedDependencies, but this requires a extensive configuration to begin with and idealy i'd like to keep up with the currently approved releases without manual interactions.

Any ideas on that? Did i miss a configuration?

Update1:

Well even trying to list all allowed dependencies in the enforcer plugin didn't work for me:

   <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.2</version>
    </dependency>
    ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>1.4.1</version>
            <executions>
                <execution>
                    <id>enforce-versions</id>
                    <goals>
                      <goal>enforce</goal>
                    </goals>
                    <configuration>
                        <rules>
                            <bannedDependencies>
                                <excludes>
                                    <exclude>*:*</exclude>
                                </excludes>
                                <includes>
                                    <include>commons-io:commons-io:1.4</include>
                                    ...
                                </includes>
                            </bannedDependencies>
                        </rules>
                        <fail>true</fail>
                    </configuration>
                </execution>
            </executions>
        </plugin>

The Build should fail here but is [INFO] BUILD SUCCESS.

Update 2:

What is even more suprising is that in the maven documentation the issue is already adressed to be fixed with changes in version 3: https://cwiki.apache.org/confluence/display/MAVEN/Maven+3.x+Compatibility+Notes#Maven3.xCompatibilityNotes-ResolutionfromLocalRepository

Resolution from Local Repository The local repository used by Maven 3.x has been enhanced to keep track from what remote repositories an artifact was resolved from. This information about an artifact's origin is used to ensure builds can only access locally cached artifacts if they have the proper repositories configured. Hence, projects that lack required remote repositories in their POM might fail when being built with Maven 3. This improves reproducibility of a build by eliminating the effects of unintended artifact sharing via the local repository.

dag
  • 1,133
  • 12
  • 25
  • I would check artifactory if it has some kind of procurement (nexus term) which solves this kind of problem...literally defining this in a maven build does not make sense, cause anyone who can change a pomfile can change this...which does not make sense in the end... – khmarbaise Feb 25 '16 at 13:18
  • as i understand the procurement feature you may switch a remote mirror to offline mode, so no new dependencies are downloaded. That s what i have already - i have a repository that contains all artifacts that are approved to be used in production applications. The problem i have is that the maven build needs more artifacts just to get the plugins themselfs to work and those dependencies mix on the client side resulting in builds that may include artifactes that are not allowed to be used. I need a strict separation of artifacts useable by maven and artifacts useable by the compiler. – dag Feb 26 '16 at 10:50
  • Maven is using artifacts of course. By the compiler you mean the JDK ? Otherwise it does not make sense, cause maven-compiler-plugin needs also artifacts otherwise you can't compile your code.Apart from that the settings.xml can be configured having separated maven-plugins and other artifacts which is usually not done. – khmarbaise Feb 26 '16 at 14:19
  • my problem is the mixing of plugin and compile/runtime dependencies. Once a maven plugin needed a artifact it s put in the local cache and maven dont care this cached artifact is not available in the non-plugin repository. That s a bug in my eyes and i try to find a way around it. – dag Feb 28 '16 at 23:18
  • For example the maven compiler plugin has a transitive dependency to commons-io:2.4 but your customer doesn't allow that for runtime dependencies - you have to use version 1.4. Now you provide a repository with only the allowed runtime dependencies and configure that in your pom.xml. Still maven will not fail if you use version 2.4 on your dependencies because it already downloaded it from the plugin-repository just to get the compiler-plugin to work... i can't believe to be the first one with this requirement – dag Feb 28 '16 at 23:23
  • If you need to force a paricular artifact and version you should use the maven-enforcer-plugin... – khmarbaise Feb 29 '16 at 09:18

1 Answers1

0

Ok i finaly figured out what caused my headache. First of all i want to have a self contained project. No special user settings.xml s to the running (with mirrors that will block other projects from beeing worked on if you need to switch).

As i said i don't want that the build uses artifacts he's not allowed to, so i have to reconfigure maven central that it won't get accessed. So this was my approach:

<repository>
  <id>central</id>
  <url>http://${company-repo-manager}/${project-repository}</url>
</repository>
...
<pluginRepository>
  <id>central</id>
  <url>http://${company-repo-manager}/${plugin-repository}</url>
</pluginRepository>

I looked like a good idea but had the above mentioned problem to mix up localy cached artifacts from plugin and project dependencies.

Now i knew that Maven 3 supposed to introduce a kind of local repo management i had a closer look at my local repository and found a file named _remote.repositories with this content:

commons-io-2.2.jar>central=
commons-io-2.2.pom>central=

Here you can see that maven remembers the repository a artifact came from, but it remembers the repositories id and not it's url! As i did configure my plugin repository and my project repository both with the id central maven mixed cached artifacts of both repositories.

The solutions finaly was to try to disable the central repository and configure project and plugin repository with a individual name:

<repository>
  <id>${project-repository}</id>
  <url>http://${company-repo-manager}/${project-repository}</url>
</repository>
<repository>
  <id>central</id>
  <name>Maven Central</name>
  <url>http://repo1.maven.org/maven2</url>
  <releases>
     <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>
...
<pluginRepository>
  <id>maven-plugins-repo</id>
  <url>http://${company-repo-manager}/${plugin-repository}</url>
</pluginRepository>
<pluginRepository>
  <id>central</id>
  <name>Maven Central</name>
  <url>http://repo1.maven.org/maven2</url>
  <releases>
     <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</pluginRepository>

Unfortunately you can not remove central from the resolution and so different projects will interact with the local build if they use a repository named central.

Maven Enforcer is a Plugin i'll still have a look for but this was at least the basic configuration issue i tried to solve.

If i start with a clean cache (e.g. in the CI build) i get exactly the build failture i expect.

Hope that helps someone trying to achieve that level of isolation. It's still not perfect as you can not remove the central repository and the artifact descriptors should be the same in all repos, but we have at least a minimal support.

Community
  • 1
  • 1
dag
  • 1,133
  • 12
  • 25