Skip to content

Commit

Permalink
adding proxy support for sms transport (MID-5061)
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed May 18, 2019
1 parent 85bcfdf commit 0d942b5
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 6 deletions.
Expand Up @@ -433,6 +433,46 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="proxyHost" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Proxy host.
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="proxyPort" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Proxy port.
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="proxyUsername" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
How to authenticate to the proxy.
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="proxyPassword" type="t:ProtectedStringType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
How to authenticate to the proxy.
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="redirectToFile" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,7 +18,6 @@
import com.evolveum.midpoint.notifications.api.events.CustomEvent;
import com.evolveum.midpoint.notifications.api.events.Event;
import com.evolveum.midpoint.notifications.api.transports.Message;
import com.evolveum.midpoint.notifications.impl.api.transports.TransportUtil;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
Expand Down Expand Up @@ -59,9 +58,9 @@
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Executor;

import static java.util.Collections.singletonList;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.testng.AssertJUnit.*;

/**
Expand Down Expand Up @@ -108,6 +107,14 @@ protected PrismObject<SystemConfigurationType> addSystemConfigurationObject(Oper
private int startHttpServer() throws IOException {
int freePort = findFreePort();
httpServer = HttpServer.create(new InetSocketAddress(freePort), 0);
httpServer.setExecutor(new Executor() {

@Override
public void execute(Runnable command) {
// TODO Auto-generated method stub

}
});
httpHandler = new MyHttpHandler();
httpServer.createContext("/send", httpHandler);
httpServer.start();
Expand Down Expand Up @@ -565,6 +572,7 @@ public void test200SendSmsUsingGet() {
result.computeStatus();
TestUtil.assertSuccess("processEvent result", result);

System.out.println("XXXXXXXXXXXXXXXXXXXX " + httpHandler.lastRequest.headers);
assertNotNull("No http request found", httpHandler.lastRequest);
assertEquals("Wrong HTTP method", "GET", httpHandler.lastRequest.method);
assertEquals("Wrong URI", "/send?number=%2B421905123456&text=hello+world", httpHandler.lastRequest.uri.toString());
Expand Down Expand Up @@ -635,6 +643,32 @@ public void test215SendSmsUsingGeneralPost() {
assertEquals("Wrong Authorization header", singletonList(expectedAuthorization), httpHandler.lastRequest.headers.get("authorization"));
assertEquals("Wrong 1st line of body", "Body=\"body\"&To=[%2B123, %2B456, %2B789]&From=from", httpHandler.lastRequest.body.get(0));
}

@Test
public void test220SendSmsViaProxy() {
final String TEST_NAME = "test220SendSmsViaProxy";
TestUtil.displayTestTitle(this, TEST_NAME);

// GIVEN
Task task = taskManager.createTaskInstance(TestNotifications.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

// WHEN
TestUtil.displayWhen(TEST_NAME);
Event event = new CustomEvent(lightweightIdentifierGenerator, "get-via-proxy", null,
"hello world via proxy", EventOperationType.ADD, EventStatusType.SUCCESS, null);
notificationManager.processEvent(event, task, result);

// THEN
TestUtil.displayThen(TEST_NAME);
result.computeStatus();
TestUtil.assertSuccess("processEvent result", result);

assertNotNull("No http request found", httpHandler.lastRequest);
assertEquals("Wrong HTTP method", "GET", httpHandler.lastRequest.method);
assertTrue("Header proxy-connection not found in request headers", httpHandler.lastRequest.headers.keySet().contains("proxy-connection"));
assertEquals("Wrong proxy-connection header", "Keep-Alive", httpHandler.lastRequest.headers.get("proxy-connection").get(0));
}

@Test
public void test300CheckVariables() {
Expand Down
Expand Up @@ -212,6 +212,31 @@ Channel: $!event.channel</code>
<transport>sms:with-get</transport>
</customNotifier>
</handler>
<handler>
<category>customEvent</category>
<expressionFilter>
<script>
<code>
event.subtype == 'get-via-proxy'
</code>
</script>
</expressionFilter>
<customNotifier>
<expression>
<script>
<code>
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
m = new NotificationMessageType()
m.setFrom("+421999000999")
m.getTo().add("+421905123456")
m.setBody(String.valueOf(event.object))
m
</code>
</script>
</expression>
<transport>sms:with-get-via-proxy</transport>
</customNotifier>
</handler>
<handler>
<category>customEvent</category>
<expressionFilter>
Expand Down Expand Up @@ -393,6 +418,21 @@ Channel: $!event.channel</code>
<logToFile>target/sms.log</logToFile>
</gateway>
</sms>
<sms name="with-get-via-proxy">
<gateway>
<urlExpression>
<script>
<!-- $$port$$ is replaced by actual port on test class initialization -->
<code>"http://127.0.0.1:$$port$$/send?number=" + encodedTo + "&amp;text=" + encodedMessageText</code>
</script>
</urlExpression>
<proxyHost>127.0.0.1</proxyHost>
<proxyPort>$$port$$</proxyPort>
<proxyUsername>a9038321</proxyUsername>
<proxyPassword>5ecr3t</proxyPassword>
<logToFile>target/sms.log</logToFile>
</gateway>
</sms>
<sms name="with-post">
<gateway>
<method>post</method>
Expand Down
4 changes: 4 additions & 0 deletions model/notifications-impl/pom.xml
Expand Up @@ -174,6 +174,10 @@
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>

<!-- Test -->
<dependency>
Expand Down
Expand Up @@ -51,6 +51,7 @@

import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
Expand Down Expand Up @@ -185,11 +186,12 @@ public void send(Message message, String transportName, Event event, Task task,
HttpMethodType method = defaultIfNull(smsGatewayConfigurationType.getMethod(), HttpMethodType.GET);
ExpressionType urlExpression = defaultIfNull(smsGatewayConfigurationType.getUrlExpression(), smsGatewayConfigurationType.getUrl());
String url = evaluateExpressionChecked(urlExpression, variables, "sms gateway request url", task, result);
LOGGER.debug("Sending SMS to URL {} (method {})", url, method);
String proxyHost = smsGatewayConfigurationType.getProxyHost();
String proxyPort = smsGatewayConfigurationType.getProxyPort();
LOGGER.debug("Sending SMS to URL {} via proxy host {} and port {} (method {})", url, proxyHost, proxyPort, method);
if (url == null) {
throw new IllegalArgumentException("No URL specified");
}

List<String> headersList = evaluateExpressionsChecked(smsGatewayConfigurationType.getHeadersExpression(), variables,
"sms gateway request headers", task, result);
LOGGER.debug("Using request headers:\n{}", headersList);
Expand All @@ -210,13 +212,29 @@ public void send(Message message, String transportName, Event event, Task task,
HttpClientBuilder builder = HttpClientBuilder.create();
String username = smsGatewayConfigurationType.getUsername();
ProtectedStringType password = smsGatewayConfigurationType.getPassword();
CredentialsProvider provider = new BasicCredentialsProvider();
if (username != null) {
CredentialsProvider provider = new BasicCredentialsProvider();
String plainPassword = password != null ? protector.decryptString(password) : null;
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, plainPassword);
provider.setCredentials(AuthScope.ANY, credentials);
builder = builder.setDefaultCredentialsProvider(provider);
}
String proxyUsername = smsGatewayConfigurationType.getProxyUsername();
ProtectedStringType proxyPassword = smsGatewayConfigurationType.getProxyPassword();
if(StringUtils.isNotBlank(proxyHost) && StringUtils.isNotBlank(proxyUsername)) {
String plainProxyPassword = proxyPassword != null ? protector.decryptString(proxyPassword) : null;
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(proxyUsername, plainProxyPassword);
HttpHost proxy;
if(StringUtils.isNotBlank(proxyPort) && isInteger(proxyPort)){
int port = Integer.parseInt(proxyPort);
proxy = new HttpHost(proxyHost, port);
} else {
proxy = new HttpHost(proxyHost);
}
provider.setCredentials(new AuthScope(proxy), credentials);
builder = builder.setDefaultCredentialsProvider(provider);
builder.setProxy(proxy);
}
HttpClient client = builder.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
ClientHttpRequest request = requestFactory.createRequest(new URI(url), HttpUtil.toHttpMethod(method));
Expand All @@ -243,6 +261,17 @@ public void send(Message message, String transportName, Event event, Task task,
LOGGER.warn("No more SMS gateways to try, notification to " + message.getTo() + " will not be sent.") ;
result.recordWarning("Notification to " + message.getTo() + " could not be sent.");
}

private static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
} catch(NullPointerException e) {
return false;
}
return true;
}

private void setHeaders(ClientHttpRequest request, List<String> headersList) {
for (String headerAsString : headersList) {
Expand Down

0 comments on commit 0d942b5

Please sign in to comment.