spring-gradle-plugins / dependency-management-plugin

A Gradle plugin that provides Maven-like dependency management functionality
686 stars 85 forks source link

Plugin disables dependency constraints #314

Closed splix closed 2 years ago

splix commented 2 years ago

I found out that having the plugin:

id 'io.spring.dependency-management' version '1.0.6.RELEASE'

breaks dependency constraints:

constraints {
    add("implementation", "org.apache.logging.log4j:log4j-core") {
        version {
            strictly("[2.15,3[")
            prefer("2.15.0")
        }
        because("CVE-2021-44228 Log4j 2 Vulnerability")
    }
}

The plugin still forces to use version 2.13.3 of the library. It seems that it makes such dependencies to be ignored because even versions with invalid syntax are accepted without any error.

Simply disabling the plugin fixes the dependency resolution, and the project starts to use the correct version of 2.15.0.

See also discussion in the comments section at https://stackoverflow.com/questions/70326473/gradle-dependency-constrains-are-not-applied

jmini commented 2 years ago

Specifically about log4j, this is an interesting blog post: https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot


The GitHub advisories database has also marked org.apache.logging.log4j:log4j-api as vulnerable.

So we tried to apply this constraints:

    constraints {
       implementation("org.apache.logging.log4j:log4j-api") {
            version {
                strictly("[2.15, 3[")
                prefer("2.15.0")
            }
            because("CVE-2021-44228 LOG4J is vulnerable to remote code execution")
        }
    }

In a gradle build where we are using:

plugins {
    //...
    id 'org.springframework.boot' version '2.5.6'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}

And it is not working as expected ./gradlew dependencies contains the lines:

\--- org.apache.logging.log4j:log4j-api:{strictly [2.15, 3[; prefer 2.15.0} -> 2.14.1 (c)

(c) - dependency constraint

Which is obviously wrong…

wilkinsona commented 2 years ago

This is, unfortunately, how Gradle works. A resolution strategy, as used by this plugin, takes precedence over a dependency constraint. You should override the log4j2 version or use a resolution strategy of your own as recommended in this blog post.

jmini commented 2 years ago

In my opinion, now that there is proper support for platforms and maven BOM files in Gradle (see Sharing dependency versions between projects), I am wondering if there is really an additional value with this io.spring.dependency-management

In my eyes unless proven otherwise this component is legacy (invented when those features were missing in Gradle).

wilkinsona commented 2 years ago

That's certainly the position that we're aiming for but we're not quite there yet for some users at least. The main advantage that this plugin has is the ability to override properties from an imported bom. For example, Spring Boot's bom manages 10+ Hibernate modules. Switching them all to a new version is a one-liner with the hibernate.version property.

NfNitLoop commented 2 years ago

Thanks for pointing me here @wilkinsona.

After my experience, I share @jmini 's opinion.

Would it be worth updating the docs for the plugin to reflect that you're aiming for its deprecation, and what advantages it provides in the meantime? (Maybe with a warning about the fact that it completely takes over Gradle's resolution strategy?)

I appreciate the work that's gone into this plugin! Dependency management is a difficult and often thankless job. (And, I take it from context, this plugin provided BOM support before Gradle did? Which is great!) But as Gradle catches up, I think having two separate dependency management strategies (Spring vs. Gradle) is going to cause more headaches like the one I had today. 😆

NfNitLoop commented 2 years ago

Would it be worth updating the docs for the plugin to reflect [...] what advantages it provides in the meantime?

Aha! To be fair, I did find the benefits documented over in the gradle plugin reference. It's just not in the dependency management plugin docs.

To manage dependencies in your Spring Boot application, you can either apply the io.spring.dependency-management plugin or use Gradle’s native bom support. The primary benefit of the former is that it offers property-based customization of managed versions, while using the latter will likely result in faster builds.