Author Message
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
I wrote a dynamic task to send an http request and retrieve the returned data. It flows like this:

CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://...");
CloseableHttpResponse response = client.execute(httpGet);
logger.info("Snap-In HTTP Response " + response.getStatusLine());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
logger.info("Snap-In HTTP Entity " + responseString);
response.close();

This works fine. Following the same format, I then tried to use web service that requires https. However, an exception ("Remote Host Closed Connection During Handshake") is always generated during client.execute(). This same call works if I make it with the Call Rest Service ED task so I know that the proper cert has been loaded.

Forgive my ignorance, but do I need to do something different for https?

Thanks!

JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
Hi Andrew, your code needs to get a SecurityContext from our com.avaya.collaboration.ssl.util.SSLUtilityFactory class. This will give you a SecurityContext that will use the provisioned trust / identity certificates for your Breeze node. FYI, the WebSphere certificate is used for the identity cert in the case that you get challenged by the far end.

Please let us know if that resolves the problem for you. Also, your encounter with the problem was more likely caused by insufficient documentation on our part than excessive ignorance on your part. We'll look into improving it.
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
Thank you, but I really am ignorant in this regard. Would you mind fleshing out the code a bit with how I would incorporate SecurityContext into my example? This is all very new to me.
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
First off, an apology. I said "SecurityContext" below and I should have said "SSLContext". Getting an SSLContext from our Factory class is as simple as:

SSLContext mySSLContext = SSLUtilityFactory.createSSLContext();

If you are working with an older service that doesn't support TLS 1.2, you may need to use the signature of the method that allows you to specify a protocol version.

Are you using Apache HTTP Client to invoke the external service? If so, this page shows how to use a custom SSLContext object once you've created it from our Factory.
https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java

Hopefully that's helpful.
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
I may be getting closer. Following the pattern you sent, I have this:

logger.info("Starting IoT section A");
SSLContext mySSLContext = SSLUtilityFactory.createSSLContext();
logger.info("Starting IoT section B");
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
mySSLContext,
new String[] { "TLSv1_2" },
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
logger.info("Starting IoT section C");
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();

I get to section B, but it never hits section C. Any thoughts as to why it gets stuck?

UPDATE:

I changed the sslsf line to:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
mySSLContext);

It gets further, but I get "Remote host closed connection during handshake" which implies that my security is still not right.
Amit.Mishra
Joined: Dec 19, 2013
Messages: 34
Offline
Here is some sample code which can clarify more on this. Please let us know if this helps clarify.

If you still get an error - can you please provide with the output of ce-report?



import java.io.IOException;

import javax.net.ssl.SSLContext;
import javax.ws.rs.core.MediaType;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;

import com.avaya.collaboration.ssl.util.SSLUtilityException;
import com.avaya.collaboration.ssl.util.SSLUtilityFactory;
import com.avaya.collaboration.util.logger.Logger;

/**
* Validator for callback URL value.
*/
public final class CallbackUrlValidatorImpl implements CallbackUrlValidator
{
private static CallbackUrlValidatorImpl instance;
private static final String BOUNDARY = "EFC-callBackUrl-validator";
private static final String CONTENT_TYPE = "Content-Type";

private CloseableHttpClient httpClient;

private SSLContext sslContext;
private AttributeReader attributeReader;
private HttpClientBuilder httpClientBuilder;

public static synchronized CallbackUrlValidatorImpl getInstance()
{
if (instance == null)
{
instance = new CallbackUrlValidatorImpl();
}
return instance;
}

private CallbackUrlValidatorImpl()
{
}

@Override
public void validate(final String callbackUrl)
{

try
{
if (!isActiveUrl(callbackUrl))
{
}
}
catch (final IOException ex)
{
final String message = ex.getMessage();

if (message != null
&& (message.contains("InvalidAlgorithmParameterException") || message
.contains("CertPathBuilderException")))
{
}
else
{
}
}
catch (final Exception ex)
{
throw ex;
}

}

private boolean isActiveUrl(final String callbackUrl) throws IOException
{
CloseableHttpResponse callbackResponse = null;
httpClient = getHttpClient();
try
{
// Validate the callback URL is alive
final HttpPost request = new HttpPost(callbackUrl);
request.setHeader(CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA
+ "; boundary=" + BOUNDARY);
final MultipartEntityBuilder builder = MultipartEntityBuilder.create().setBoundary(BOUNDARY);
builder.addTextBody(Constants.CALLBACK_URL, callbackUrl);
final HttpEntity multipart = builder.build();
request.setEntity(HttpUtil.convertToNonBlockingHttpEntity(multipart));
callbackResponse = httpClient.execute(request);
final StatusLine statusLine = callbackResponse.getStatusLine();
final int statusCode = statusLine.getStatusCode();
if (statusCode == HttpStatus.SC_OK)
{
return true;
}
else
{
final String message = "Callback url " + callbackUrl + " is invalid. Returned status code : "
+ statusCode + ", status line : " + statusLine;
}
}
finally
{
try
{
if (null != callbackResponse)
{
callbackResponse.close();
}
}
catch (final IOException e)
{
// Ignore this
}
}
}

public CloseableHttpClient getHttpClient()
{
if (httpClient == null)
{
final AttributeReader attReader = getAttributeReader();
final RequestConfig requestConfig =
RequestConfig.custom().setLocalAddress(HttpUtil.getInetAddress())
.setConnectionRequestTimeout(attReader.getHttpConnectionRequestTimeout())
.setConnectTimeout(attReader.getHttpConnectTimeout())
.setSocketTimeout(attReader.getHttpSocketTimeout()).build();
httpClient = getHttpClientBuilder().setSslcontext(getSSLContext())
.setHostnameVerifier(new AllowAllHostnameVerifier()).setDefaultRequestConfig(requestConfig)
.setMaxConnTotal(attReader.getHttpMaxTotalConnections())
.setMaxConnPerRoute(attReader.getHttpMaxConnectionsPerHost())
.build();
}
return httpClient;
}

private HttpClientBuilder getHttpClientBuilder()
{
if (httpClientBuilder == null)
{
httpClientBuilder = HttpClients.custom();
}
return httpClientBuilder;
}

private AttributeReader getAttributeReader()
{
if (attributeReader == null)
{
attributeReader = new AttributeReaderImpl();
}
return attributeReader;
}

public void setHttpClient(final CloseableHttpClient httpClient)
{
this.httpClient = httpClient;
}

public synchronized void resetHttpClient()
{
if (this.httpClient != null)
{
try
{
this.httpClient.close();
}
catch (final IOException e)
{
}
this.httpClient = null;
}
}

protected SSLContext getSSLContext()
{
if (sslContext == null)
{
try
{
sslContext = SSLUtilityFactory.createSSLContext();
}
catch (final SSLUtilityException e)
{
}
}
return sslContext;
}


}
RajeshChandrashekar
Joined: Oct 27, 2016
Messages: 60
Offline
for your reference :



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import com.avaya.collaboration.ssl.util.SSLUtilityException;
import com.avaya.collaboration.ssl.util.SSLUtilityFactory;

public class SampleHttpsClient {


public String useApacheHttpClient(String ip) throws SSLUtilityException, ClientProtocolException,
IOException
{
SSLContext sslContext = SSLUtilityFactory.createSSLContext();
HttpClient client =
HttpClients.custom().setSslcontext(sslContext)
.setHostnameVerifier(new AllowAllHostnameVerifier()).build();
HttpGet getMethod =
new HttpGet("https://..");
HttpResponse response = client.execute(getMethod);
BufferedReader inputStream =
new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

String line = "";
StringBuilder result = new StringBuilder();
while ((line = inputStream.readLine()) != null)
{
result.append(line);
}
inputStream.close();
((CloseableHttpClient) client).close();

return result.toString();
}

}

Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
I followed the example that Rajesh supplied and still get "Remote hosts closed connection during handshake." I am attaching the report from ce-report.

Here is my code. I can execute this same URI from an ED workflow using the Call REST Services task so I expect that my certificate is installed correctly.

package com.arrow.arrowtask;

import org.json.JSONObject;

import com.avaya.app.entity.Instance;
import com.avaya.app.entity.NodeInstance;
import com.roobroo.bpm.model.BpmNode;
import com.avaya.collaboration.util.logger.Logger;
import org.apache.commons.lang.StringUtils;
import java.util.List;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.HttpRequest;
import org.apache.http.util.*;
import org.apache.http.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.HttpResponse;
import com.avaya.collaboration.ssl.util.SSLUtilityFactory;
import com.avaya.collaboration.ssl.util.SSLUtilityException;
import javax.net.ssl.SSLContext;


public class ArrowTaskExecution extends NodeInstance {

private static Logger logger = Logger.getLogger(ArrowTaskExecution.class);

public ArrowTaskExecution(Instance instance, BpmNode node) {
super(instance, node);
}

public Object execute() throws Exception {
JSONObject obj = new JSONObject();

try {
SSLContext sslContext = SSLUtilityFactory.createSSLContext();
HttpClient client =
HttpClients.custom().setSslcontext(sslContext).setHostnameVerifier(new AllowAllHostnameVerifier()).build();
HttpGet getMethod =
new HttpGet("https://api.arrowconnect.io/api/v1/kronos/telemetries/devices/b4aa3369582d6de540d99c89a7b7059c08046823?fromTimestamp=2016-09-26T00:00:00Z&toTimestamp=2016-10-26T00:00:00Z");
getMethod.addHeader("x-auth-token", "f6c9f6f22aa31a4a2e77dc61c7e431575049c29c957b46ad9473aa0604d89958");
getMethod.addHeader("Accept", "application/json");
HttpResponse response = client.execute(getMethod);
logger.info("Starting IoT section D");
BufferedReader inputStream = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

String line = "";
StringBuilder result = new StringBuilder();
while ((line = inputStream.readLine()) != null)
{
result.append(line);
}
inputStream.close();
((CloseableHttpClient) client).close();
} catch (Exception ex) {
logger.info(ex.getMessage());
ex.printStackTrace();
}

Filename cereport-breeze2-mgmt-201611100805.tgz [Disk] Download
RajeshChandrashekar
Joined: Oct 27, 2016
Messages: 60
Offline
thanks for the logs, our team is having a look, just a though on the TLS version you used when you say the same works with ED REST task.

Also could you try creating the context using the protocol as below:


import com.avaya.collaboration.ssl.util.SSLProtocolType

SSLProtocolType protocolType = SSLProtocolType.TLSv1_2;
SSLContext sslContext = SSLUtilityFactory.createSSLContext(protocolType);
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
Is SSLProtocolType.TLSv1_2 new? It won't resolve during compilation. SSLProtocolType.TLS does. I assume this means that my SDK is out-of-date.

I downloaded SDK-3.2-0.0-0732005. Can I simply run install.bat or do I need to do anything with the old SDK beforehand? It has been a long time since I installed the original SDK that I'm a bit rusty. Thanks.
RajeshChandrashekar
Joined: Oct 27, 2016
Messages: 60
Offline
hi,
Yes you can just execute install.bat and you might need to change the collaboration api version in your pom.xml to the one you downloaded.
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
I am sorry to say that after upgrading both the Breeze and ED SDKs to 3.2 (while going through Maven hell), I still get "Remote host closed connection during handshake." Any idea where I can look next? Here is my code:

package com.arrow.arrowtask;

import org.json.JSONObject;

import com.avaya.app.entity.Instance;
import com.avaya.app.entity.NodeInstance;
import com.roobroo.bpm.model.BpmNode;
import com.avaya.collaboration.util.logger.Logger;
import org.apache.commons.lang.StringUtils;
import java.util.List;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.HttpRequest;
import org.apache.http.util.*;
import org.apache.http.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.HttpResponse;
import com.avaya.collaboration.ssl.util.SSLUtilityFactory;
import com.avaya.collaboration.ssl.util.SSLUtilityException;
import javax.net.ssl.SSLContext;
import com.avaya.collaboration.ssl.util.SSLProtocolType;


public class ArrowTaskExecution extends NodeInstance {

private static Logger logger = Logger.getLogger(ArrowTaskExecution.class);

public ArrowTaskExecution(Instance instance, BpmNode node) {
super(instance, node);
}

public Object execute() throws Exception {
JSONObject obj = new JSONObject();

try {
SSLProtocolType protocolType = SSLProtocolType.TLSv1_2;
SSLContext sslContext = SSLUtilityFactory.createSSLContext(protocolType);

HttpClient client =
HttpClients.custom().setSslcontext(sslContext).setHostnameVerifier(new AllowAllHostnameVerifier()).build();
HttpGet getMethod =
new HttpGet("https://api.arrowconnect.io/api/v1/kronos/telemetries/devices/b4aa3369582d6de540d99c89a7b7059c08046823?fromTimestamp=2016-09-26T00:00:00Z&toTimestamp=2016-10-26T00:00:00Z");
getMethod.addHeader("x-auth-token", "f6c9f6f22aa31a4a2e77dc61c7e431575049c29c957b46ad9473aa0604d89958");
getMethod.addHeader("Accept", "application/json");
HttpResponse response = client.execute(getMethod);
BufferedReader inputStream = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

String line = "";
StringBuilder result = new StringBuilder();
while ((line = inputStream.readLine()) != null)
{
result.append(line);
}
inputStream.close();
((CloseableHttpClient) client).close();
} catch (Exception ex) {
logger.info(ex.getMessage());
ex.printStackTrace();
}
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
Hi Andrew, this is looking like a job for tshark. Sorry that you're continuing to run into problems. Can you please do the following, where "www.yourdomain.com" is the service that you are trying to access.

tshark -w /tmp/https.pcap -i eth1 host www.yourdomain.com
# do your test
# ^C
# then to display
tshark -r /tmp/https.pcap

If it's not clear to you what the problem is, please feel free to post the pcap file here and we can take a look.
Andrew.Prokop
Joined: Oct 28, 2014
Messages: 179
Offline
Stupid programmer trick. I got it to work!

Thanks to everyone for your help. I am on my way to adding IoT support into Breeze workflows.
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
Fantastic! Is there anything you can share about your solution that may help out others that encounter this thread in the future?
Go to:   
Mobile view