BJ-368: external port restricting (#41)

* BJ-368: external port restricting

* BJ-368: external port restricting
This commit is contained in:
Anatolii Karlov 2019-02-05 15:12:20 +03:00 committed by GitHub
parent bc0715217b
commit 9cc73b6e99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 28 deletions

View File

@ -19,10 +19,9 @@
<description>Проксик для тестирования и эмуляции запросов к банку</description>
<properties>
<service.port>8022</service.port>
<service.secondary.ports>8080</service.secondary.ports>
<server.port>${service.port} ${service.secondary.ports}</server.port>
<exposed.ports>${server.port}</exposed.ports>
<server.port>8022</server.port>
<server.rest.port>8080</server.rest.port>
<exposed.ports>${server.port} ${server.rest.port}</exposed.ports>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.maintainer>Anatoly Cherkasov &lt;a.cherkasov@rbkmoney.com&gt;</project.maintainer>
<dockerfile.base.service.tag>2a8b44ac628c1bdb729abd04ed7a2a54676e574b</dockerfile.base.service.tag>

View File

@ -1,14 +1,21 @@
package com.rbkmoney.proxy.mocketbank.configuration;
import com.rbkmoney.woody.api.flow.WFlow;
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* This is the configuration class for configuring the {@link ServletWebServerFactory}
@ -20,31 +27,80 @@ import java.util.List;
@Configuration
public class TomcatEmbeddedConfiguration {
@Value("${server.port}")
private String mainPort;
public static final String HEALTH = "/actuator/health";
@Value("#{'${server.secondary.ports}'.split(',')}")
private List<String> secondaryPorts;
@Value("${server.rest.port}")
private int restPort;
@Value("/${server.rest.endpoint}/")
private String restEndpoint;
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
Connector[] additionalConnectors = this.additionalConnector();
if (additionalConnectors.length > 0) {
tomcat.addAdditionalTomcatConnectors(additionalConnectors);
}
Connector connector = new Connector();
connector.setPort(restPort);
tomcat.addAdditionalTomcatConnectors(connector);
return tomcat;
}
private Connector[] additionalConnector() {
List<Connector> result = new ArrayList<>();
for (String port : secondaryPorts) {
Connector connector = new Connector();
connector.setPort(Integer.valueOf(port));
result.add(connector);
}
return result.toArray(new Connector[]{});
@Bean
public FilterRegistrationBean externalPortRestrictingFilter() {
Filter filter = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String servletPath = request.getServletPath();
if ((request.getLocalPort() == restPort)
&& !(servletPath.startsWith(restEndpoint) || servletPath.startsWith(HEALTH))) {
response.sendError(404, "Unknown address");
return;
}
filterChain.doFilter(request, response);
}
};
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.setOrder(-100);
filterRegistrationBean.setName("httpPortFilter");
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean woodyFilter() {
WFlow wFlow = new WFlow();
Filter filter = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if ((request.getLocalPort() == restPort)
&& request.getServletPath().startsWith(restEndpoint)) {
wFlow.createServiceFork(() -> {
try {
filterChain.doFilter(request, response);
} catch (IOException | ServletException e) {
sneakyThrow(e);
}
}).run();
return;
}
filterChain.doFilter(request, response);
}
private <E extends Throwable, T> T sneakyThrow(Throwable t) throws E {
throw (E) t;
}
};
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.setOrder(-50);
filterRegistrationBean.setName("woodyFilter");
filterRegistrationBean.addUrlPatterns(restEndpoint + "*");
return filterRegistrationBean;
}
}

View File

@ -18,7 +18,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
@RestController
@RequestMapping(value = "/mocketbank")
@RequestMapping("/${server.rest.endpoint}")
public class MocketBankController {
private final Logger log = LoggerFactory.getLogger(this.getClass());

View File

@ -15,9 +15,10 @@ info:
stage: dev
---
server:
port: @service.port@
secondary:
ports: @service.secondary.ports@
port: @server.port@
rest:
port: @server.rest.port@
endpoint: mocketbank
---
proxy-mocketbank-mpi:
url: http://127.0.0.1:8018

View File

@ -37,7 +37,7 @@ import static org.junit.Assert.fail;
properties = {
"restTemplate.networkTimeout=10000",
"server.port=7021",
"server.secondary.ports=7022",
"server.rest.port=7022",
"proxy-mocketbank-mpi.url=http://127.0.0.1:${server.port}"
}
)

View File

@ -0,0 +1,50 @@
package com.rbkmoney.proxy.mocketbank.configuration;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import static com.rbkmoney.proxy.mocketbank.configuration.TomcatEmbeddedConfiguration.HEALTH;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"server.rest.port=65434"}
)
public class ExternalPortRestrictingTest {
private static final String FAKE_REST_PATH = "/you-not-found";
private static final String MAPPED_REST_ENDPATH = "/term_url";
@Value("${server.rest.port}")
private int restPort;
@Value("/${server.rest.endpoint}")
private String restEndpoint;
@Test
public void test() throws IOException {
String baseUrl = "http://localhost:" + restPort;
String restUrl = baseUrl + restEndpoint;
HttpGet httpGetTransaction = new HttpGet(restUrl + MAPPED_REST_ENDPATH);
HttpGet httpGetHealth = new HttpGet(baseUrl + HEALTH);
HttpGet httpGetWrongAddress = new HttpGet(baseUrl + FAKE_REST_PATH);
assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, getHttpClient().execute(httpGetTransaction).getStatusLine().getStatusCode());
assertEquals(HttpStatus.SC_OK, getHttpClient().execute(httpGetHealth).getStatusLine().getStatusCode());
assertEquals(HttpStatus.SC_NOT_FOUND, getHttpClient().execute(httpGetWrongAddress).getStatusLine().getStatusCode());
}
private CloseableHttpClient getHttpClient() {
return HttpClientBuilder.create().build();
}
}