Update Spring Bean Property Across Multiple Servers - java

Here is my scenario: I have a Spring Bean called APIBean which acts as an API client to a remote REST service. This Bean contains a property called hostName which is the IP Address of the Remote Server. This functions as the base URI when the APIBean client makes REST calls. The initial value of this hostName property is pulled from application.properties.
The challenge I have is that the hostName property is subject to change. I have a web form where a User will update the hostName property when its address changes. This is pretty straightforward in a single instance environment, but my application is distributed in AWS and behind an Elastic Load Balancer.
So how should I go about applying this change to all other instances of this Spring Boot application?
I've looked at Spring Cloud Config which externalizes application.properties to a centralized Git repository. It even includes a /refresh endpoint which you can hit with a POST request to update Beans annotated with RefreshScope. But this endpoint only refreshes the single instance you are accessing. It does not affect any other distributed instance.
These frameworks are great and I feel the solution is close but I need a little help with the last mile. This must be a common development issue with distributed applications. How can we update a Spring Bean property across multiple servers?

I think you are looking for Spring Cloud Bus: https://github.com/spring-cloud/spring-cloud-bus.

Related

Oauth 2 : Spring Boot - Separate Resource server protecting Microservices

For my recent project, I have created a separate resource server using spring boot. Resource Server is configured in a way that it will check for 2 legged and 3 legged access to an API and also validates the JWT token. Resource server is an independent spring boot jar running in its container.
We have created several microservices using Spring Boot which are executable jars, deployed and running independently in their container. Resource server will protect end points exposed in these microservices. For that, I have created a RestController in resource server in which end point is exposed which will call the microservice end point when request comes in. for e.g
Microservice.java - Running at port 8080
#RequestMapping("/getUser")
public String getUserName(){
return "xyz";
}
Resource Server - Running at port 8090
ResourceServerController.java
#RequestMapping("/userInfo")
public String getUserName(){
// calling above microservice using rest template
}
There can be several end point in a several microservices and as we have to protect them, is it right to proxy every end point in the rest controller of a resource server? I am not sure whether it is a correct approach. Other approach which we think of is to create a jar of resource server and deployed as a dependency with every microservice. In this way, we do not need to proxy end points in the Rest Controller of Resource Server.
Just wanted to know the best way to Protect microservices using separate resource server.
Sharing Libraries is not a recommended option. A huge benefit of Microservices is independence and that would go for a toss if you do this.
A better option would be to see if you can provide access to API based on scope. That way, when your Authorization Server issues JWT token, it sends all the applicable scope for the user.
Then, in your Resource Server(s) , you can enable access to Microservice using the following annotation in Spring Boot
    
#PreAuthorize("#oauth2.hasScope('read')")
Another approach is, you can create roles and PreAuthorize using Roles.
If the above options doesn't work out, the current approach that you are following based on Proxy Service is perfectly fine. Only aspect that you should consider is to see if the JWT token validation can be moved to the respective Microservices so that all your services are protected.
Again, Code duplicacy is perfectly fine when you are implementing Microservices and if that is your main concern, don't hesitate to add the same logic in every service. With Microservices, Duplication is better than wrong abstraction
JWT is the self-contained token, which can store scope of access for REST-service users. JWT is issued by the Authorization server.In your Resource servers, you should validate every request from REST-service users. If your Resource server(s) runs on spring-boot you can use the following annotation:
#PreAuthorize("hasRole('ROLE_VIEW')")
As for the part where your services call each other, there no need to use JWT because no REST-service users involved.
Microservices can be secured by simple BasicAuth, CORS or locate them in one network without access from an external network

Best practice to map webservice endpoint in client

this question is more of a design/architecture question. Let's say I have a server application that provides Spring-based webservices and a client application. So currently I have a few Java classes on the client side where the endpoint of the service is hardcoded (e.g. http://myserver/some/webservice).
What is a good way to map the client side properly with the webservice? Just off the top of my head: is there a library that helps evaluate URLs with parameters and maps them to the properties of a POJO using reflection?
As I understand your question, 2 options pop into my head:
1) Eureka- Service Discovery for Spring Cloud.
It can help you by giving your client the Eureka URL and the Eureka will supply the client with the desired service URL. so if there the server is going down Eureka can point the client to a back up server (it will be seamless to the client) or even different URL's to different services on the same server.
2) Spring Cloud Config
A configuration service that contains the URL's in the DB, the client will pull those URLs from there and will make the calls to a configurable URI's.
Spring allow you to update those URL's in the DB and it will use spring cloud config to push the new URL's down to the clients without any downtime... (might fit you better if you are not interested in load balancing and other features provided by Eureka)

AWS , Spring Boot, Tomcat : Session replication

I have a spring boot application which uses embedded tomcat. The app is hosted on multiple EC2 instances, which auto scale if required and some of which may be killed/restarted. So, effectively there are 3 instances of the app running , and requests are routed from the load balancer to any of these instances.
I am trying to track user sessions on my app. I started with implementing container level session management using tomcat HttpSession. But it is not able to track sessions across instances. On researching a bit, I got to know that i need something like session replication.
My app is not running a tomcat cluster, it has 3 independent instances of the API which do not talk to each other in anyway. I am not planning to change that and not sure if it is possible with AWS as it does not encourage multicast communication for this purpose.
Also, I do not want to setup/manage a separate DB (like redis with spring session) just for this purpose, because I only need session Ids for logging, and I need to do that in a lightweight manner.
Is there any other way to manage sessions across instances ? or for my purpose, would it be better to just implement some custom code which can check for session id/token passed to and fro between the frontend and backend.
The goal is to externalize the sessions from your application server so that you can autoscale, restart, load balance etc. without worrying about breaking a User's session.
Honestly on AWS using the Spring stack, I would recommend Spring Session + Redis. I've used it countless times and it is very easy to implement. You can leverage AWS Elasticache which manages the Redis cluster for you (like RDS does for relational DBs).
You could write your own custom implementation of Spring Session with a backing store of S3, Dynamo, etc. But is that really any better than the Redis implementation? I'd recommend the path of least resistance.

How to get the address of the calling remote client of an EJB method in JBoss AS7

i have a distributed application that consists of one server, the JBoss AS7 on which the frontend and the backend of the application run.
Several clients, running on other machines in a network obtain the JNDI initial context of the JBoss to get certain objects.
Each client is unique and needs to be identified without doing any configuration on them. My approach is to get their address and map the data related to them (pool of stuff, evenly mapped between all connected clients).
How can i obtain the IP address of the calling client of an EJB method?
I already found 'hacks' that describe how to get the information out of the thread name (used for example in JBoss 4.x), but that always returns something like:
EJB default - 7
See How can you get the calling ip address on an ejb call?
If you provide a code snippet or a method call on some context, can you please add the source of it? I was unable to find something by searching for EJB3, Remoting3 and similar stuff
Just an idea,
May be use can expose your ejb through a rest based web service layer. If you do so it is easy to find remote host name and may also use filter servlet to allow or disallow a request.
You can use #EJB to inject your bean into rest class assuming you will use JAX-RS.

IBM WESB/WAS JCA security configuration

I'm working with IBM tools. I have a Websphere ESB (WESB) and a CICS transaction gateway (CTG). The basic set-up is as follows:
A SOAP service needs data from CICS. The SOAP-service is connecting to service bus (WESB) to handle data and protocol transformation and then WESB calls the CTG which in turn calls CICS and the reply is handled vice verse (synchronously). WESB calls the CTG using Resource Adapter and JCA connector (or CICS adapter as it is called in WESB). Now, I have all the pieces in place and working.
My question is about the security, and even though I'm working with WESB, the answer is probably the same as in Websphere Application Server (WAS). The Resource Adaper is secured using JAAS - J2C authentication data. I have configured the security using J2C authentication data entry, so basically I have a reference in the application I'm running and at runtime the application does a lookup for the security attributes from the server. So basically I'm always accessing the CICS adapter with the same security reference.
My problem is that I need to access the resource in more dynamic way
in the future. The security cannot be welded into the application
anymore but instead given as a parameter.
Could some WESB or WAS guru help me out, how this could be done in WESB/WAS exactly?
Can you elaborate a bit further? I don't work with CTG but I believe it is no different from other resources such as JDBC or JMS resource.
On the CTG resource adapter, you have identified credentials that are used for all calls to the CICS.
This is similar to what we do when we work with a Data Source and this approach is agreeable to most people.
I do not see how the J2C credential is welded to the application. The configuration is done # WAS/WESB. The application would simply work with the JNDI resources on the server to which the J2C aliases are configured.
If you elaborate on the dynamic requirement folks can help out.
HTH
Manglu

Categories