If configured, HTTP proxy will be used for callbacks to the NearRT RIC.
Change-Id: Iaed4b2a61cf4f8037e7c4374b4945836104a640b
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
Issue-ID: NONRTRIC-317
12 files changed:
"tags": ["A1-EI (enrichment information)"]
}}
},
"tags": ["A1-EI (enrichment information)"]
}}
},
- "host": "localhost:38585",
"definitions": {
"producer_ei_job_request": {
"description": "The body of the EI producer callbacks for EI job creation and deletion",
"definitions": {
"producer_ei_job_request": {
"description": "The body of the EI producer callbacks for EI job creation and deletion",
description: This page lists all the rest apis for the service.
version: "1.0"
servers:
description: This page lists all the rest apis for the service.
version: "1.0"
servers:
-- url: //localhost:38585/
tags:
- name: A1-EI (enrichment information)
description: Consumer Controller
tags:
- name: A1-EI (enrichment information)
description: Consumer Controller
endpoints:
web:
exposure:
endpoints:
web:
exposure:
+ # Enabling of springboot actuator features. See springboot documentation.
include: "loggers,logfile,health,info,metrics,threaddump,heapdump"
logging:
include: "loggers,logfile,health,info,metrics,threaddump,heapdump"
logging:
+ # Configuration of logging
level:
ROOT: ERROR
org.springframework: ERROR
level:
ROOT: ERROR
org.springframework: ERROR
file:
name: /var/log/enrichment-coordinator-service/application.log
server:
file:
name: /var/log/enrichment-coordinator-service/application.log
server:
+ # Configuration of the HTTP/REST server. The parameters are defined and handeled by the springboot framework.
+ # See springboot documentation.
port : 8434
http-port: 8083
ssl:
port : 8434
http-port: 8083
ssl:
key-password: policy_agent
key-alias: policy_agent
app:
key-password: policy_agent
key-alias: policy_agent
app:
- filepath: /opt/app/enrichment-coordinator-service/data/application_configuration.json
+ # Configuration of the trust store used for the HTTP client (outgoing requests)
+ # The file location and the password for the truststore is only relevant if trust-store-used == true
+ # Note that the same keystore as for the server is used.
trust-store-used: false
trust-store-password: policy_agent
trust-store: /opt/app/enrichment-coordinator-service/etc/cert/truststore.jks
trust-store-used: false
trust-store-password: policy_agent
trust-store: /opt/app/enrichment-coordinator-service/etc/cert/truststore.jks
+ # Configuration of usage of HTTP Proxy for the southbound accesses.
+ # The HTTP proxy (if configured) will only be used for accessing NearRT RIC:s
+ http.proxy-host:
+ http.proxy-port: 0
vardata-directory: /var/enrichment-coordinator-service
vardata-directory: /var/enrichment-coordinator-service
import java.lang.invoke.MethodHandles;
import java.util.concurrent.atomic.AtomicInteger;
import java.lang.invoke.MethodHandles;
import java.util.concurrent.atomic.AtomicInteger;
+import org.oransc.enrichment.configuration.WebClientConfig.HttpProxyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
+import reactor.netty.tcp.ProxyProvider.Proxy;
import reactor.netty.tcp.TcpClient;
/**
import reactor.netty.tcp.TcpClient;
/**
private final String baseUrl;
private static final AtomicInteger sequenceNumber = new AtomicInteger();
private final SslContext sslContext;
private final String baseUrl;
private static final AtomicInteger sequenceNumber = new AtomicInteger();
private final SslContext sslContext;
+ private final HttpProxyConfig httpProxyConfig;
- /**
- * Note that only http (not https) will work when this constructor is used.
- *
- * @param baseUrl
- */
- public AsyncRestClient(String baseUrl) {
- this(baseUrl, null);
- }
-
- public AsyncRestClient(String baseUrl, SslContext sslContext) {
+ public AsyncRestClient(String baseUrl, @Nullable SslContext sslContext, @Nullable HttpProxyConfig httpProxyConfig) {
this.baseUrl = baseUrl;
this.sslContext = sslContext;
this.baseUrl = baseUrl;
this.sslContext = sslContext;
+ this.httpProxyConfig = httpProxyConfig;
}
public Mono<ResponseEntity<String>> postForEntity(String uri, @Nullable String body) {
}
public Mono<ResponseEntity<String>> postForEntity(String uri, @Nullable String body) {
logger.debug("{} HTTP error status = '{}', body '{}'", traceTag, exception.getStatusCode(),
exception.getResponseBodyAsString());
} else {
logger.debug("{} HTTP error status = '{}', body '{}'", traceTag, exception.getStatusCode(),
exception.getResponseBodyAsString());
} else {
- logger.debug("{} HTTP error", traceTag, t);
+ logger.debug("{} HTTP error {}", traceTag, t.getMessage());
- private TcpClient createTcpClientSecure(SslContext sslContext) {
- return TcpClient.create(ConnectionProvider.newConnection()) //
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
- .secure(c -> c.sslContext(sslContext)) //
- .doOnConnected(connection -> {
- connection.addHandlerLast(new ReadTimeoutHandler(30));
- connection.addHandlerLast(new WriteTimeoutHandler(30));
- });
+ private boolean isHttpProxyConfigured() {
+ return httpProxyConfig != null && httpProxyConfig.httpProxyPort() > 0
+ && !httpProxyConfig.httpProxyHost().isEmpty();
- private TcpClient createTcpClientInsecure() {
- return TcpClient.create(ConnectionProvider.newConnection()) //
+ private TcpClient createTcpClient() {
+ TcpClient client = TcpClient.create(ConnectionProvider.newConnection()) //
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(30));
connection.addHandlerLast(new WriteTimeoutHandler(30));
});
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(30));
connection.addHandlerLast(new WriteTimeoutHandler(30));
});
+ if (this.sslContext != null) {
+ client = client.secure(c -> c.sslContext(sslContext));
+ }
+ if (isHttpProxyConfigured()) {
+ client = client.proxy(proxy -> proxy.type(Proxy.HTTP).host(httpProxyConfig.httpProxyHost())
+ .port(httpProxyConfig.httpProxyPort()));
+ }
+ return client;
}
private WebClient createWebClient(String baseUrl, TcpClient tcpClient) {
HttpClient httpClient = HttpClient.from(tcpClient);
}
private WebClient createWebClient(String baseUrl, TcpClient tcpClient) {
HttpClient httpClient = HttpClient.from(tcpClient);
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() //
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) //
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() //
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) //
private Mono<WebClient> getWebClient() {
if (this.webClient == null) {
try {
private Mono<WebClient> getWebClient() {
if (this.webClient == null) {
try {
- if (this.sslContext != null) {
- TcpClient tcpClient = createTcpClientSecure(sslContext);
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- } else {
- TcpClient tcpClient = createTcpClientInsecure();
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- }
+ TcpClient tcpClient = createTcpClient();
+ this.webClient = createWebClient(this.baseUrl, tcpClient);
} catch (Exception e) {
logger.error("Could not create WebClient {}", e.getMessage());
return Mono.error(e);
} catch (Exception e) {
logger.error("Could not create WebClient {}", e.getMessage());
return Mono.error(e);
import javax.net.ssl.KeyManagerFactory;
import org.oransc.enrichment.configuration.WebClientConfig;
import javax.net.ssl.KeyManagerFactory;
import org.oransc.enrichment.configuration.WebClientConfig;
+import org.oransc.enrichment.configuration.WebClientConfig.HttpProxyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final SslContextFactory sslContextFactory;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final SslContextFactory sslContextFactory;
+ private final HttpProxyConfig httpProxyConfig;
public AsyncRestClientFactory(WebClientConfig clientConfig) {
if (clientConfig != null) {
this.sslContextFactory = new CachingSslContextFactory(clientConfig);
public AsyncRestClientFactory(WebClientConfig clientConfig) {
if (clientConfig != null) {
this.sslContextFactory = new CachingSslContextFactory(clientConfig);
+ this.httpProxyConfig = clientConfig.httpProxyConfig();
+ logger.warn("No configuration for web client defined, HTTPS will not work");
this.sslContextFactory = null;
this.sslContextFactory = null;
+ this.httpProxyConfig = null;
- public AsyncRestClient createRestClient(String baseUrl) {
+ public AsyncRestClient createRestClientNoHttpProxy(String baseUrl) {
+ return createRestClient(baseUrl, false);
+ }
+
+ public AsyncRestClient createRestClientUseHttpProxy(String baseUrl) {
+ return createRestClient(baseUrl, true);
+ }
+
+ private AsyncRestClient createRestClient(String baseUrl, boolean useHttpProxy) {
if (this.sslContextFactory != null) {
try {
if (this.sslContextFactory != null) {
try {
- return new AsyncRestClient(baseUrl, this.sslContextFactory.createSslContext());
+ return new AsyncRestClient(baseUrl, this.sslContextFactory.createSslContext(),
+ useHttpProxy ? httpProxyConfig : null);
} catch (Exception e) {
String exceptionString = e.toString();
logger.error("Could not init SSL context, reason: {}", exceptionString);
}
}
} catch (Exception e) {
String exceptionString = e.toString();
logger.error("Could not init SSL context, reason: {}", exceptionString);
}
}
- return new AsyncRestClient(baseUrl);
+ return new AsyncRestClient(baseUrl, null, httpProxyConfig);
}
private class SslContextFactory {
}
private class SslContextFactory {
package org.oransc.enrichment.configuration;
package org.oransc.enrichment.configuration;
-import javax.validation.constraints.NotEmpty;
-
+import org.oransc.enrichment.configuration.WebClientConfig.HttpProxyConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@EnableConfigurationProperties
@ConfigurationProperties()
public class ApplicationConfig {
@EnableConfigurationProperties
@ConfigurationProperties()
public class ApplicationConfig {
- @NotEmpty
- @Getter
- @Value("${app.filepath}")
- private String localConfigurationFilePath;
@Getter
@Value("${app.vardata-directory}")
@Getter
@Value("${app.vardata-directory}")
@Value("${app.webclient.trust-store}")
private String sslTrustStore = "";
@Value("${app.webclient.trust-store}")
private String sslTrustStore = "";
+ @Value("${app.webclient.http.proxy-host:\"\"}")
+ private String httpProxyHost = "";
+
+ @Value("${app.webclient.http.proxy-port:0}")
+ private int httpProxyPort = 0;
+
public WebClientConfig getWebClientConfig() {
public WebClientConfig getWebClientConfig() {
+ HttpProxyConfig httpProxyConfig = ImmutableHttpProxyConfig.builder() //
+ .httpProxyHost(this.httpProxyHost) //
+ .httpProxyPort(this.httpProxyPort) //
+ .build();
return ImmutableWebClientConfig.builder() //
.keyStoreType(this.sslKeyStoreType) //
.keyStorePassword(this.sslKeyStorePassword) //
return ImmutableWebClientConfig.builder() //
.keyStoreType(this.sslKeyStoreType) //
.keyStorePassword(this.sslKeyStorePassword) //
.isTrustStoreUsed(this.sslTrustStoreUsed) //
.trustStore(this.sslTrustStore) //
.trustStorePassword(this.sslTrustStorePassword) //
.isTrustStoreUsed(this.sslTrustStoreUsed) //
.trustStore(this.sslTrustStore) //
.trustStorePassword(this.sslTrustStorePassword) //
+ .httpProxyConfig(httpProxyConfig) //
public String trustStore();
public String trustStore();
+ @Value.Immutable
+ public interface HttpProxyConfig {
+ public String httpProxyHost();
+
+ public int httpProxyPort();
+ }
+
+ public HttpProxyConfig httpProxyConfig();
+
@Autowired
public ConsumerCallbacks(ApplicationConfig config, EiTypes eiTypes, EiJobs eiJobs) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig());
@Autowired
public ConsumerCallbacks(ApplicationConfig config, EiTypes eiTypes, EiJobs eiJobs) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig());
- this.restClient = restClientFactory.createRestClient("");
+ this.restClient = restClientFactory.createRestClientUseHttpProxy("");
this.eiTypes = eiTypes;
this.eiJobs = eiJobs;
}
this.eiTypes = eiTypes;
this.eiJobs = eiJobs;
}
@Autowired
public ProducerCallbacks(ApplicationConfig config, EiTypes eiTypes) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig());
@Autowired
public ProducerCallbacks(ApplicationConfig config, EiTypes eiTypes) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig());
- this.restClient = restClientFactory.createRestClient("");
+ this.restClient = restClientFactory.createRestClientNoHttpProxy("");
this.eiTypes = eiTypes;
}
this.eiTypes = eiTypes;
}
public ProducerSupervision(ApplicationConfig applicationConfig, EiProducers eiProducers, EiJobs eiJobs,
EiTypes eiTypes, ConsumerCallbacks consumerCallbacks) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(applicationConfig.getWebClientConfig());
public ProducerSupervision(ApplicationConfig applicationConfig, EiProducers eiProducers, EiJobs eiJobs,
EiTypes eiTypes, ConsumerCallbacks consumerCallbacks) {
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(applicationConfig.getWebClientConfig());
- this.restClient = restClientFactory.createRestClient("");
+ this.restClient = restClientFactory.createRestClientNoHttpProxy("");
this.eiJobs = eiJobs;
this.eiProducers = eiProducers;
this.eiTypes = eiTypes;
this.eiJobs = eiJobs;
this.eiProducers = eiProducers;
this.eiTypes = eiTypes;
import org.oransc.enrichment.clients.AsyncRestClient;
import org.oransc.enrichment.clients.AsyncRestClientFactory;
import org.oransc.enrichment.configuration.ApplicationConfig;
import org.oransc.enrichment.clients.AsyncRestClient;
import org.oransc.enrichment.clients.AsyncRestClientFactory;
import org.oransc.enrichment.configuration.ApplicationConfig;
+import org.oransc.enrichment.configuration.ImmutableHttpProxyConfig;
import org.oransc.enrichment.configuration.ImmutableWebClientConfig;
import org.oransc.enrichment.configuration.WebClientConfig;
import org.oransc.enrichment.configuration.ImmutableWebClientConfig;
import org.oransc.enrichment.configuration.WebClientConfig;
+import org.oransc.enrichment.configuration.WebClientConfig.HttpProxyConfig;
import org.oransc.enrichment.controller.ConsumerSimulatorController;
import org.oransc.enrichment.controller.ProducerSimulatorController;
import org.oransc.enrichment.controllers.consumer.ConsumerConsts;
import org.oransc.enrichment.controller.ConsumerSimulatorController;
import org.oransc.enrichment.controller.ProducerSimulatorController;
import org.oransc.enrichment.controllers.consumer.ConsumerConsts;
ResponseEntity<String> resp = restClient().getForEntity(url).block();
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
ResponseEntity<String> resp = restClient().getForEntity(url).block();
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
- String indented = (new JSONObject(resp.getBody())).toString(4);
+ JSONObject jsonObj = new JSONObject(resp.getBody());
+ jsonObj.remove("host");
+ String indented = jsonObj.toString(4);
try (PrintStream out = new PrintStream(new FileOutputStream("api/ecs-api.json"))) {
out.print(indented);
}
try (PrintStream out = new PrintStream(new FileOutputStream("api/ecs-api.json"))) {
out.print(indented);
}
private AsyncRestClient restClient(boolean useTrustValidation) {
WebClientConfig config = this.applicationConfig.getWebClientConfig();
private AsyncRestClient restClient(boolean useTrustValidation) {
WebClientConfig config = this.applicationConfig.getWebClientConfig();
+ HttpProxyConfig httpProxyConfig = ImmutableHttpProxyConfig.builder() //
+ .httpProxyHost("") //
+ .httpProxyPort(0) //
+ .build();
config = ImmutableWebClientConfig.builder() //
.keyStoreType(config.keyStoreType()) //
.keyStorePassword(config.keyStorePassword()) //
config = ImmutableWebClientConfig.builder() //
.keyStoreType(config.keyStoreType()) //
.keyStorePassword(config.keyStorePassword()) //
.isTrustStoreUsed(useTrustValidation) //
.trustStore(config.trustStore()) //
.trustStorePassword(config.trustStorePassword()) //
.isTrustStoreUsed(useTrustValidation) //
.trustStore(config.trustStore()) //
.trustStorePassword(config.trustStorePassword()) //
+ .httpProxyConfig(httpProxyConfig).build();
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config);
AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config);
- return restClientFactory.createRestClient(baseUrl());
+ return restClientFactory.createRestClientNoHttpProxy(baseUrl());
}
private AsyncRestClient restClient() {
}
private AsyncRestClient restClient() {
InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);
Loggers.useJdkLoggers();
mockWebServer = new MockWebServer();
InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);
Loggers.useJdkLoggers();
mockWebServer = new MockWebServer();
- clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString());
+ clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString(), null, null);