From: PatrikBuhr Date: Fri, 17 Apr 2020 06:58:02 +0000 (+0200) Subject: Added support for https X-Git-Tag: 2.0.0~69^2 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F24%2F3424%2F2;p=nonrtric.git Added support for https The agent listens to two ports: - 8081 for http - 8433 for https The agent can communicate using http or https. A self signed certificate is used, which built into the docker container. Change-Id: Ia54d00ea849bd656678a76dfeab5d10c6e4dc1a2 Issue-ID: NONRTRIC-195 Signed-off-by: PatrikBuhr --- diff --git a/policy-agent/Dockerfile b/policy-agent/Dockerfile index 26ce5317..da9fd448 100644 --- a/policy-agent/Dockerfile +++ b/policy-agent/Dockerfile @@ -25,7 +25,7 @@ WORKDIR /opt/app/policy-agent RUN mkdir -p /var/log/policy-agent RUN mkdir -p /opt/app/policy-agent/etc/cert/ -EXPOSE 8081 +EXPOSE 8081 8433 ADD /config/* /opt/app/policy-agent/config/ ADD target/${JAR} /opt/app/policy-agent/policy-agent.jar diff --git a/policy-agent/config/application.yaml b/policy-agent/config/application.yaml index 5416a4d2..b1284942 100644 --- a/policy-agent/config/application.yaml +++ b/policy-agent/config/application.yaml @@ -19,7 +19,14 @@ logging: org.springframework.web.reactive.function.client.ExchangeFunctions: ERROR org.oransc.policyagent: INFO file: /var/log/policy-agent/application.log -app: - filepath: /opt/app/policy-agent/config/application_configuration.json server: - port : 8081 + port : 8433 + ssl: + key-store-type: PKCS12 + key-store-password: policy_agent + key-store: classpath:keystore.jks + key-password: policy_agent +app: + filepath: /opt/app/policy-agent/config/application_configuration.json + + diff --git a/policy-agent/src/main/java/org/oransc/policyagent/BeanFactory.java b/policy-agent/src/main/java/org/oransc/policyagent/BeanFactory.java index 93e1739f..e2874cb7 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/BeanFactory.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/BeanFactory.java @@ -22,12 +22,15 @@ package org.oransc.policyagent; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.catalina.connector.Connector; import org.oransc.policyagent.clients.A1ClientFactory; import org.oransc.policyagent.configuration.ApplicationConfig; import org.oransc.policyagent.repository.Policies; import org.oransc.policyagent.repository.PolicyTypes; import org.oransc.policyagent.repository.Rics; import org.oransc.policyagent.repository.Services; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -70,4 +73,19 @@ class BeanFactory { return new ObjectMapper(); } + @Bean + public ServletWebServerFactory servletContainer() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addAdditionalTomcatConnectors(getHttpConnector()); + return tomcat; + } + + private static Connector getHttpConnector() { + Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); + connector.setScheme("http"); + connector.setPort(8081); + connector.setSecure(false); + return connector; + } + } diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java index f0b2ce33..ef1acfc1 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java @@ -21,11 +21,16 @@ package org.oransc.policyagent.clients; import io.netty.channel.ChannelOption; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; import java.lang.invoke.MethodHandles; +import javax.net.ssl.SSLException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; @@ -45,36 +50,24 @@ import reactor.netty.tcp.TcpClient; */ public class AsyncRestClient { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final WebClient client; + private WebClient webClient = null; private final String baseUrl; public AsyncRestClient(String baseUrl) { - - TcpClient tcpClient = TcpClient.create() // - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // - .doOnConnected(connection -> { - connection.addHandler(new ReadTimeoutHandler(10)); - connection.addHandler(new WriteTimeoutHandler(30)); - }); - HttpClient httpClient = HttpClient.from(tcpClient); - ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); - - this.client = WebClient.builder() // - .clientConnector(connector) // - .baseUrl(baseUrl) // - .build(); - this.baseUrl = baseUrl; } public Mono> postForEntity(String uri, @Nullable String body) { logger.debug("POST uri = '{}{}''", baseUrl, uri); Mono bodyProducer = body != null ? Mono.just(body) : Mono.empty(); - RequestHeadersSpec request = client.post() // - .uri(uri) // - .contentType(MediaType.APPLICATION_JSON) // - .body(bodyProducer, String.class); - return retrieve(request); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.post() // + .uri(uri) // + .contentType(MediaType.APPLICATION_JSON) // + .body(bodyProducer, String.class); + return retrieve(request); + }); } public Mono post(String uri, @Nullable String body) { @@ -84,29 +77,38 @@ public class AsyncRestClient { public Mono postWithAuthHeader(String uri, String body, String username, String password) { logger.debug("POST (auth) uri = '{}{}''", baseUrl, uri); - RequestHeadersSpec request = client.post() // - .uri(uri) // - .headers(headers -> headers.setBasicAuth(username, password)) // - .contentType(MediaType.APPLICATION_JSON) // - .bodyValue(body); - return retrieve(request) // - .flatMap(this::toBody); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.post() // + .uri(uri) // + .headers(headers -> headers.setBasicAuth(username, password)) // + .contentType(MediaType.APPLICATION_JSON) // + .bodyValue(body); + return retrieve(request) // + .flatMap(this::toBody); + }); } public Mono> putForEntity(String uri, String body) { logger.debug("PUT uri = '{}{}''", baseUrl, uri); - RequestHeadersSpec request = client.put() // - .uri(uri) // - .contentType(MediaType.APPLICATION_JSON) // - .bodyValue(body); - return retrieve(request); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.put() // + .uri(uri) // + .contentType(MediaType.APPLICATION_JSON) // + .bodyValue(body); + return retrieve(request); + }); } public Mono> putForEntity(String uri) { logger.debug("PUT uri = '{}{}''", baseUrl, uri); - RequestHeadersSpec request = client.put() // - .uri(uri); - return retrieve(request); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.put() // + .uri(uri); + return retrieve(request); + }); } public Mono put(String uri, String body) { @@ -116,8 +118,11 @@ public class AsyncRestClient { public Mono> getForEntity(String uri) { logger.debug("GET uri = '{}{}''", baseUrl, uri); - RequestHeadersSpec request = client.get().uri(uri); - return retrieve(request); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.get().uri(uri); + return retrieve(request); + }); } public Mono get(String uri) { @@ -127,8 +132,11 @@ public class AsyncRestClient { public Mono> deleteForEntity(String uri) { logger.debug("DELETE uri = '{}{}''", baseUrl, uri); - RequestHeadersSpec request = client.delete().uri(uri); - return retrieve(request); + return getWebClient() // + .flatMap(client -> { + RequestHeadersSpec request = client.delete().uri(uri); + return retrieve(request); + }); } public Mono delete(String uri) { @@ -160,4 +168,40 @@ public class AsyncRestClient { } } + private static SslContext createSslContext() throws SSLException { + return SslContextBuilder.forClient() // + .trustManager(InsecureTrustManagerFactory.INSTANCE) // + .build(); + } + + private static WebClient createWebClient(String baseUrl, SslContext sslContext) { + TcpClient tcpClient = TcpClient.create() // + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // + .secure(c -> c.sslContext(sslContext)) // + .doOnConnected(connection -> { + connection.addHandler(new ReadTimeoutHandler(10)); + connection.addHandler(new WriteTimeoutHandler(30)); + }); + HttpClient httpClient = HttpClient.from(tcpClient); + ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); + + return WebClient.builder() // + .clientConnector(connector) // + .baseUrl(baseUrl) // + .build(); + } + + private Mono getWebClient() { + if (this.webClient == null) { + try { + SslContext sslContext = createSslContext(); + this.webClient = createWebClient(this.baseUrl, sslContext); + } catch (SSLException e) { + logger.error("Could not create WebClient {}", e.getMessage()); + return Mono.error(e); + } + } + return Mono.just(this.webClient); + } + } diff --git a/policy-agent/src/main/resources/keystore.jks b/policy-agent/src/main/resources/keystore.jks index 574a585b..3cd6bb79 100644 Binary files a/policy-agent/src/main/resources/keystore.jks and b/policy-agent/src/main/resources/keystore.jks differ diff --git a/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java b/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java index 6905c70c..0027cca1 100644 --- a/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java +++ b/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java @@ -659,7 +659,7 @@ public class ApplicationTest { } private String baseUrl() { - return "http://localhost:" + port; + return "https://localhost:" + port; } private String jsonString() { diff --git a/policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java b/policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java index 2b66a353..cdf614c2 100644 --- a/policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java +++ b/policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java @@ -123,6 +123,7 @@ public class MockPolicyAgent { logger.error("Could not load json schema ", e); } } + policyTypes.put(ImmutablePolicyType.builder().name("").schema("{}").build()); } }