-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c6c54d7
commit 4ef63e7
Showing
5 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
|
||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-parent</artifactId> | ||
<version>2.1.2.RELEASE</version> | ||
<relativePath/> | ||
</parent> | ||
|
||
<groupId>netwatch</groupId> | ||
<artifactId>gateway</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
<name>gateway</name> | ||
<description>Microservice for providing the API Gateway.</description> | ||
|
||
<properties> | ||
<java.version>11</java.version> | ||
<spring-cloud.version>Greenwich.RC2</spring-cloud.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.cloud</groupId> | ||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>32.1.3-jre</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<version>1.18.30</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.cloud</groupId> | ||
<artifactId>spring-cloud-dependencies</artifactId> | ||
<version>${spring-cloud.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-maven-plugin</artifactId> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<repositories> | ||
<repository> | ||
<id>spring-milestones</id> | ||
<name>Spring Milestones</name> | ||
<url>https://repo.spring.io/milestone</url> | ||
</repository> | ||
</repositories> | ||
|
||
</project> |
21 changes: 21 additions & 0 deletions
21
api-gateway/src/main/java/netwatch/gateway/GatewayApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package netwatch.gateway; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
@SpringBootApplication | ||
@EnableZuulProxy | ||
public class GatewayApplication { | ||
|
||
public static void main(String[] args) { | ||
SpringApplication.run(GatewayApplication.class, args); | ||
} | ||
|
||
@Bean | ||
public RestTemplate restTemplate() { | ||
return new RestTemplate(); | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
api-gateway/src/main/java/netwatch/gateway/filters/AuthFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package netwatch.gateway.filters; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import com.google.common.util.concurrent.RateLimiter; | ||
import com.netflix.zuul.ZuulFilter; | ||
import com.netflix.zuul.context.RequestContext; | ||
|
||
import lombok.extern.java.Log; | ||
|
||
// This class is a Zuul pre-filter responsible for authenticating and authorizing incoming requests. | ||
// It verifies the validity of a token by requesting an Authentication Service. | ||
// It applies the RBAC Pattern by requesting an Authorization Service. | ||
// It includes rate limiting to prevent abuse of the service. | ||
// @author Antonio Scardace | ||
// @version 1.0 | ||
|
||
@Log | ||
@Component | ||
public class AuthFilter extends ZuulFilter { | ||
|
||
private final RestTemplate restTemplate; | ||
private final String authenticationUrl = System.getenv("AUTHN_URL"); | ||
private final String authorizationUrl = System.getenv("AUTHZ_URL"); | ||
private static RateLimiter rateLimiter = RateLimiter.create(10); | ||
|
||
@Autowired | ||
public AuthFilter(RestTemplate restTemplate) { | ||
this.restTemplate = restTemplate; | ||
} | ||
|
||
@Override | ||
public String filterType() { | ||
return "pre"; | ||
} | ||
|
||
@Override | ||
public int filterOrder() { | ||
return 2; | ||
} | ||
|
||
@Override | ||
public boolean shouldFilter() { | ||
return true; | ||
} | ||
|
||
private boolean checkAuthorization(String userRole, String method, String object) { | ||
String authUrl = this.authorizationUrl + "/check" + "?role=" + userRole + "&method=" + method + "&object=" + object; | ||
return "true".equals(restTemplate.getForObject(authUrl, String.class)); | ||
} | ||
|
||
private boolean isTokenValid(String apiKey) { | ||
String url = this.authenticationUrl + "/validate/" + apiKey; | ||
return "true".equals(restTemplate.getForObject(url, String.class)); | ||
} | ||
|
||
private String getUserRole(String apiKey) { | ||
String url = this.authenticationUrl + "/role/" + apiKey; | ||
return restTemplate.getForObject(url, String.class); | ||
} | ||
|
||
// Zuul pre-filter for authentication and authorization. | ||
// Checks if the rate limit has been exceeded. If so, responds with a 429 status code. | ||
// Otherwise, proceeds with the authentication and authorization checks. | ||
// If the request is a valid sign-in or sign-up operation the filter allows the request to proceed. | ||
// If the request has a valid API Key and is authorized, the filter allows the request to proceed. | ||
// Otherwise, sets a Zuul response with a 403 Forbidden status, indicating a "Forbidden Request". | ||
// The user authorization verification is based on its role, HTTP method, and requested route. | ||
|
||
@Override | ||
public Object run() { | ||
RequestContext context = RequestContext.getCurrentContext(); | ||
|
||
if (!rateLimiter.tryAcquire(1)) { | ||
context.setSendZuulResponse(false); | ||
context.setResponseStatusCode(429); | ||
context.setResponseBody("Rate limit exceeded."); | ||
|
||
log.warning("Rate limit exceeded."); | ||
return null; | ||
} | ||
|
||
String apiKey = context.getRequest().getHeader("X-API-Key"); | ||
String method = context.getRequest().getMethod(); | ||
String uri = context.getRequest().getRequestURI(); | ||
String route = uri.substring(context.getRequest().getContextPath().length()); | ||
|
||
List<String> allowedRoutes = Arrays.asList( | ||
"/authentication/signin", | ||
"/authentication/signup" | ||
); | ||
|
||
if ("POST".equals(method) && allowedRoutes.contains(route)) | ||
return null; | ||
|
||
if (apiKey != null && | ||
this.isTokenValid(apiKey) && | ||
this.checkAuthorization(this.getUserRole(apiKey), method, route)) | ||
return null; | ||
|
||
context.setSendZuulResponse(false); | ||
context.setResponseStatusCode(403); | ||
context.setResponseBody("Forbidden Request."); | ||
|
||
log.warning("Forbidden Request: " + method + " " + route); | ||
return null; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
api-gateway/src/main/java/netwatch/gateway/filters/LoggingFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package netwatch.gateway.filters; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import com.netflix.zuul.ZuulFilter; | ||
import com.netflix.zuul.context.RequestContext; | ||
|
||
import lombok.extern.java.Log; | ||
|
||
// This class is a Zuul pre-filter responsible for logging incoming requests. | ||
// It logs the method and URI of each incoming request. | ||
// This filter receives incoming requests allowed by the Rate Limiter and passes them to other Filters. | ||
// @author Antonio Scardace | ||
// @version 1.0 | ||
|
||
@Log | ||
@Component | ||
public class LoggingFilter extends ZuulFilter { | ||
|
||
@Override | ||
public String filterType() { | ||
return "pre"; | ||
} | ||
|
||
@Override | ||
public int filterOrder() { | ||
return 1; | ||
} | ||
|
||
@Override | ||
public boolean shouldFilter() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public Object run() { | ||
RequestContext context = RequestContext.getCurrentContext(); | ||
String method = context.getRequest().getMethod(); | ||
String uri = context.getRequest().getRequestURI(); | ||
|
||
log.info("Incoming request: " + method + " " + uri); | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
server.port = 8888 | ||
|
||
zuul.routes.idm-users.path = /users/** | ||
zuul.routes.idm-users.url = http://identity-manager:6000/api/users/ | ||
|
||
zuul.routes.idm-roles.path = /roles/** | ||
zuul.routes.idm-roles.url = http://identity-manager:6000/api/roles/ | ||
|
||
zuul.routes.idm-authentication.path = /authentication/** | ||
zuul.routes.idm-authentication.url = http://identity-manager:6000/api/authentication/ | ||
|
||
zuul.routes.idm-authorization.path = /authorization/** | ||
zuul.routes.idm-authorization.url = http://identity-manager:6000/api/authorization/ | ||
|
||
zuul.routes.manager-contacts.path = /contacts/** | ||
zuul.routes.manager-contacts.url = http://manager:6000/api/contacts/ | ||
|
||
zuul.routes.manager-utilities.path = /utilities/** | ||
zuul.routes.manager-utilities.url = http://manager:6000/api/utilities/ | ||
|
||
zuul.routes.manager-observations.path = /observations/** | ||
zuul.routes.manager-observations.url = http://manager:6000/api/observations/ |