spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.25k stars 37.98k forks source link

Deprecate remoting technologies support #25379

Closed mbazos closed 4 years ago

mbazos commented 4 years ago

The original issue here was closed https://github.com/spring-projects/spring-framework/issues/24434 and I think this needs to be brought back up again.

@bclozel made a few valid points:

Doing this would be a breaking change and we would need to create a new artifact for that. This is typically the type of change we apply for major releases.

These classes have been part of spring-web since Spring Framework 1.1.

I guess it's hard to balance the severity of the issue and the amount of unsafe setup required to trigger it. Tools warning about such vulnerabilities don't usually have that context and they can only convey more information to users about the context of this vulnerability.

In this case, and especially since this new warning seems to be a misunderstanding, I don't think we should move this code now.

The issue was closed but I think this issue should be opened and accounted for at least for the next major release of the spring framework which @bclozel had mentioned as a viable option. Before closing this ticket out it would be nice if there was a set plan on how to handle this in future major releases of spring-framework.

I did fork the spring-framework repo and split the rmi code into a new module `spring-rmi' and this isn't a difficult thing to do and making this part of a major release would be nice as when people upgrade to 6.x they can accommodate for this code no longer being in spring-web. https://github.com/mbazos/spring-framework/tree/feature/split-remoting-to-new-module

jhoeller commented 4 years ago

@bclozel Instead of splitting those out into yet another artifact, let's rather deprecate the entire RMI and HTTP Invoker support in 5.3 and remove those bits in 6.0 altogether. Such a style of remoting is old school and not recommendable for many reasons these days. Also, the Oracle JDK team intends to deprecate serialization in some form; we can easily anticipate that here.

jhoeller commented 4 years ago

I would even go as far as deprecating the Hessian support as well (a similar style with similar drawbacks even if it is not Java serialization based), leaving spring-web without any remoting contents except for JAX-WS, and allowing us to get rid of the Caucho dependency in 6.0 altogether.

Also, JMS Invoker should be deprecated and removed along with HTTP invoker since it was meant as a direct equivalent, leaving spring-jms without any remoting contents as well.

bclozel commented 4 years ago

Alright let's do that; we'll deprecate everything under:

So just leaving org.springframework.remoting.jaxws support in place.

Now depending on how security tools are implemented, they might be relying on artifact names + versions only, not a particular class on classpath. If this is the case, deprecating and removing this support might not solve the problem in the long term, unless vendors update their detection heuristics as a result.

Given how brittle the current systems seems to be (critical warnings to users for a duplicate CVE from a disbanded CNA), I'm not really optimistic right now. Users will have to reach out to their providers to make this right if the warning isn't gone by Spring Framework 6.0.

mbazos commented 4 years ago

@jhoeller Thanks for weighing in on this. I really like the idea of deprecating them now and removing them in 6.0.

jhoeller commented 4 years ago

@bclozel All we'll keep in place for the time being is the remoting infrastructure for the JAX-WS and the EJB access support then. Those might fade away themselves along with some major EE support changes in 6.0 but that's a somewhat different topic.

The remoting.rmi package contains some bits used by the Remote EJB access support but that's not a showstopper. We could still aim to deprecate the entire RMI package and use @SuppressWarnings for the RmiClientInterceptorUtils call in the EJB invoker for the time being.

kablumandal commented 2 years ago

@bclozel Instead of splitting those out into yet another artifact, let's rather deprecate the entire RMI and HTTP Invoker support in 5.3 and remove those bits in 6.0 altogether. Such a style of remoting is old school and not recommendable for many reasons these days. Also, the Oracle JDK team intends to deprecate serialization in some form; we can easily anticipate that here.

I understand it is old way, but what about backward compatibility? it should be a way to convert rmi to http.

skarpushin commented 1 year ago

Such a style of remoting is old school and not recommendable for many reasons these days

@jhoeller would you be so kind and elaborate on 2 things: "why is it old school" and "what are those many reasons"?

I'll explain a bit why I'm asking.

First -- I'm just eager to know what are those many reasons that I might not be aware of, while I should be.

Second -- there is a tool for the job. For internet-scale applications HttpInvoker might be considered inappropriate, but not all applications are of internet-scale. And not all software solutions consist of hundreds microservices created using 5 different platforms (java, .net, go, python, nodejs, etc...)

Third -- HttpInvoker allows to cut corners and waive necessity to create REST API servers and client and just allow different instances to conveniently talk to each other, this decreases efforts and hence cost. This is a huge benefit from project budget and schedule perspective.

For those who concerned about security -- they must refrain from usage of Java's Object serialization and use JSON instead with list of whitelisted classes and beans.

And forth -- I also cannot imagine why is this considered old school. New approaches (i.e. Feign client) gravitate towards same paradigm that allows you to use Java interfaces without explicitly implementing REST API client. So people want to write less boiler-plate code (probably now more than ever) and in that sense HttpInvoker achieves the same.

rsaddey commented 1 year ago

IMHO removing all of Spring Remoting might have been both, an unfortunate and unneccessary move. Why? It was caused by security concerns. Those security concerns ultimately emerge from Java Object serialization. Java Object serialization is just one alternative to transmit values and entities.

To make my point clear: Spring emerged as a better alternative to EJB. Quite successfully! It now voids the remote invocation of Spring Beans methods by removing Spring Remoting. And thus is no longer a replacement for EJB.

Instead of removing all of Spring Remoting, I would have wished for Spring Remoting to support other serialization methods: Such as JSON. And this is what it comes down to: JSON is just a standards - vendor and platform independent - pattern to transport data and entities.

So why did Spring Remoting not take this path?

cristianb1989 commented 10 months ago

Is there any option offered by the Spring team to still have support for RMI when upgrading from Spring 5 to Spring 6? Our company uses Spring RMI (via HttpInvoker) for internal/intranet services and right now we're stuck to Spring 5 and can't upgrade to Spring 6 because of Spring RMI removal.

mefernandez commented 10 months ago

@bclozel Instead of splitting those out into yet another artifact, let's rather deprecate the entire RMI and HTTP Invoker support in 5.3 and remove those bits in 6.0 altogether. Such a style of remoting is old school and not recommendable for many reasons these days. Also, the Oracle JDK team intends to deprecate serialization in some form; we can easily anticipate that here.

I upgraded to Spring Boot 3.2.0 today and found this package is completely gone! Some pointers to how to do this in "new school" would be much appreciated.

elfoxus commented 6 months ago

Well, kinda sad how they managed situation :D Just drop those libs after 5 short comments and it's gone lol.

mbazos commented 6 months ago

@elfoxus I disagree this was reported back in 2020 and the spring team released this as a major update to Spring Framework 6.x. I feel they did the right thing here and there was plenty of lead time for this. I imagine they did this because there are better alternatives than using Spring RMI and Java Serialization.

With that being said it doesn't matter if you are in a situation where your app needs this and you are in the middle of a Spring 6.x upgrade. You could take the Spring RMI code from Spring 5.x and port it to Spring 6.x. I don't think this would be a lot of work to make that happen it just doesn't seem like it's something Spring wants to support anymore.

jeacott1 commented 4 months ago

@mbazos What in your view are better alternatives? I agree that RMI and java serialization are terrible options, but spring remoting did more than this. The current rsocket spring 6 remoting support is nowhere near as clean or seamless to use right now and could imo seriously benefit from the now gone remoting framework.

mbazos commented 4 months ago

@jeacott1 FWIW using jackson json + http is a better experience in general than RMI with Java Serialization...though that's not a 1:1 with exceptions/error you could communicate that via the JSON response message. If you need something more RMI like and are not a fan of rsocket then gRPC is pretty great in the Java ecosystem. I haven't personally used rsocket but have had great success with gRPC + Java.

Here is some more information: https://www.reddit.com/r/java/comments/1b8bee0/comment/ktp69x9/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button

jeacott1 commented 4 months ago

@mbazos as I said - I'm not using RMI and I don't want to. Rsocket is great, but its nowhere near as transparent to use as the serviceExporters were - it now takes a ton of custom rsocket controller boilerplate to expose any services in spring. Hessian and Burlap were supported out of the box, required no RMI nor java serialisation and were completely transparent.
gRPC is a terrible option imo - it requires custom IDL + protobuf which requires code generation and is very invasive - its nowhere near transparent. Protobuf has been eclipsed by Fury now as a serializer anyway and I could have trivially replaced hessian with it in the now defunct HessianServiceExporter. I could have also leveraged the machinery and replaced the transport with rsocket. Now it feels like we're back in the dark ages where transports take a ton of work.

mbazos commented 3 months ago

@jeacott1 you don't like my suggestions that's fine. It's time to move on.