In a microservice architecture, it is crucial to restrict access to the APIs. So that we do not run into the problem that every microservice calls another and create a dependency mess. For that reason, services should only accept requests from specific services in which their IP addresses are whitelisted. That can be accomplished using Spring Boot Security. In this tutorial, we discuss how to configure Spring Boot security to restrict requests to a specifc IP address range.
An imaginary scenario
Let’s assume we have two microservices for a music player application, User
and Song
. The Song
microservice interacts often with the User
microservice to get the necessary information. But we don’t want any other services to access the User
service for whatever reason. For that, our objective is to restrict incoming requests to those that originated from the Song
service. Both services are also behind a load balancer, so we need to take that into consideration when implementing the solution. To understand the use case better, have a look at the following diagram,
Restricting incoming requests to certain IP range with Spring Boot security
Before implementing anything, we need to add the Spring Boot security dependency to the classpath. In the Maven project, we can do that by adding spring-boot-starter-security as follow,
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Spring Security has a nice feature that can restrict incoming requests. If any does not match the criteria defined, the client will get a 403 (forbidden) response. So all we have to do is to create a SecurityConfig
file that extends WebSecurityConfigurerAdapter
as follows,
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String HAS_SONG_SERVICE_IPS = "hasIpAddress('90.100.1.0/22') or hasIpAddress('140.134.165.0/20')";
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST,"/v1/**").access(HAS_SONG_SERVICE_IPS);
}
}
In the above code, we intentionally disable the csrf
token since the service exposes APIs only and has no web interface. Then we need to specify which path we intend to apply authorization. Lastly, limit the APIs based on an IP address range.
We can apply the IP restriction in two ways, one using the hasIpAddress()
method that accepts a single IP or IP range or passes a string to the access
method and provide as many IP or IP range as we want. For the current example, the assumption was that we have more than one IP range. Hence, we use the latter.
Now if we run the program, nothing works. As stated earlier in the use case section, the User
microservice is behind a load balancer, hence, it rejects all the requests. That’s because the client IP is stored in X-Forwarded-For
that Spring security does not handle by default. The simplest solution is to use the X-Forwarded-For
value instead. For that, we need to add the following configuration to the application.properties
,
server.use-forward-headers=true
After that, we should get the result as expected, and incoming requests are filtered properly.
Conclusion
In this article, we covered how to use Spring Boot Security to restrict requests to IP address range. Only applying the filter only doesn’t work as in most environments services are behind load balancers. Therefore, one should set the X-Forwarded-For flag to true.
Besides Spring Security, there is another approach to restrict incoming requests by creating a filter. We cover that in the “Spring Boot filter incoming requests based on IP” post.
Inline/featured images credits
- Featured image by Michal Jarmoluk from Pixabay