Author Message
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
I have gone through importing the certificate for my remote server to the WebSphere store. I am now attempting to use Jersey to create an SSL client in order to post requests to remote servers. I am running into the error below:

Error 500: com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

I am creating the SSL Context using the Breeze library provided as example in the Outboundhttps sample from 3.4:


JacksonJsonProvider jsonProvider = new JacksonJsonProvider(this.mapper);
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);

HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
ClientConfig config = new DefaultClientConfig();
SSLContext ctx = null;
try {
ctx = SSLUtilityFactory.createSSLContext(SSLProtocolType.TLSv1_2);
logger.fine("SSL context created");
Log.debug("SSL context created");
} catch (SSLUtilityException e) {
logger.fine("Unable to create SSL factory");
Log.debug(e, "Unable to create SSL factory", e.getMessage());
e.printStackTrace();
}

config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hostnameVerifier, ctx));


this.client = Client.create(conf);
quetwo
Joined: Apr 6, 2018
Messages: 20
Offline
You actually have to use the Apache HTTPS client that is included in the Websphere/Breeze context rather than use another client like Jersey. Jersey will use the default HTTPS cert store, which is blank rather than the Breeze SSL Cert Store, which is pushed down from SMGR.

You can use the GSON library after you make your call to decode the JSON packet into an object.
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
I'm passing the breeze SSL context created via SSLUtilityFactory.createSSLContext into the jersey config, which should work. I will try the other client though to check.
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
As I'd mentioned in another post, our 3.4 SDK has a sample app that shows how to invoke an HTTP web service using Apache HTTP Client. You won't be able to subscribe for certificate changes as you're on 3.2, but the rest of the code should give you a head start on using HTTP Client.

I agree that Jersey "should work" if passing a SecurityContext, but there are potentially some other factors at play here. We've seen some classloader conflicts with Jersey due to the fact that we have to use "Parent First" classloading with Breeze. This means that if there are some classes provided with Breeze/WebSphere and the same classes provided by Jersey libraries in your snap-in, the Breeze version will be selected. In some cases, these will be older versions of the conflicting class. I don't know if that's what's causing this problem, but it's a definite possibility.
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
Same issue using Apache client, copied over the same HttpClient and Provider that the sample uses, and received the same error, IO Excepton: Received fatal alert: handshake_failure
.

Can you confirm that the certshould be imported to only the WebSphere cert store?



String request = "client_id=" + clientId + "&client_secret=" + clientSecret + "&grant_type=" + grantType + "&scope=" + scope;
logger.fine("request = " + request);

try {
final HttpClient client = this.httpClientProvider.getHttpClientBasedOnSSLContext();
final HttpPost httpPost = new HttpPost("https://websec-int.cable.comcast.com/as/token.oauth2");
StringEntity entity = new StringEntity(request);
httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

logger.fine("Executing Post to Websec");
final HttpResponse response = client.execute(httpPost);
final HttpEntity responseEntity = response.getEntity();
EntityUtils.consume(responseEntity);
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
One thing I had to change was the "NoopHostNameVerifier" since that does not exist until version 4.4 of library, and the server I'm using has 4.2. I changed it to "new AllowAllHostNameVerifier()"

public synchronized HttpClient getHttpClientBasedOnSSLContext() throws SSLUtilityException

{
if (client == null)
{
final AttributeReader attReader = getAttributeReader();
RequestConfig requestConfig;
try
{
requestConfig = getRequestConfigBuilder()
.setLocalAddress(InetAddress.getByName(getMyFqdnOrIpAddress()))
.setConnectionRequestTimeout(attReader.getHttpConnectionRequestTimeout())
.setConnectTimeout(attReader.getHttpConnectTimeout())
.setSocketTimeout(attReader.getHttpSocketTimeout()).build();
final SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
getSSLContext(),
new AllowAllHostnameVerifier());
final Registry<ConnectionSocketFactory> registry = RegistryBuilder
.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
final HttpClientConnectionManager cm = new BasicHttpClientConnectionManager(registry);
client = getHttpClientBuilder().setConnectionManager(cm).setDefaultRequestConfig(requestConfig)
.setMaxConnTotal(attReader.getHttpMaxTotalConnections())
.setMaxConnPerRoute(attReader.getHttpMaxConnectionsPerHost())
.build();
}
catch (final UnknownHostException e)
{
LOGGER.error("Caught UnknownHostException");
}
}
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
Hi Michael, other possible reasons that this could fail are a cipher suite mismatch or a TLS version conflict. Are you explicitly asking for a TLS version from SSLUtilityFactory and do you know if this matches an acceptable version on your far-end server? Is your far-end server picky about cipher suites? It's possible that the chain of trust hasn't been established, but I generally see a different Exception when that's the problem (something like "PKIX Path Building Failed").

I'll ask one more time, is there any chance you could upgrade to a more recent version of Breeze? We've made enhancements in the TLS arena and (I think) in our cipher suites / encryption libraries.

There are 2 ways that you may be able to get more details on what exactly is failing:
1) Look at debug logs on the remote server
2) Use wireshark or tshark to do a sniffer trace. The TLS handshake is of course carried out in the clear.
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
Edit: we cross posted, yes I'm asking for TLS1.2 which the endpoint supports. There are plans to upgrade Breeze on this instance but that is down the road, and I don't want to halt development waiting for an upgrade.

How can I access Websphere logging levels? According to the below, I should be able to access websphere admin and set these levels according to the link below.

It also appears you can modify some of these via "ce logon", but I can't figure out the cryptic commands necessary to enable what I'm looking for.

http://www-01.ibm.com/support/docview.wss?uid=nas8N1012952

JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
"ce logon" does indeed turn WAS logging up to FINEST. You can then watch the WAS log by doing a "ce logw" or view it in vi with "ce logv"
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
And to answer your earlier question, the Websphere trust store is the only one that matters for outbound HTTPS connections from Breeze. For INCOMING HTTPS connections to Breeze, the Security trust/identity certificates are the ones that matter.

Generally, however, when adding trusted certs, it doesn't hurt to use the option to add to all trust stores.
MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
But "ce logon" only turns on tracing for these Levels,

Level= *=info:com.ibm.ws.sip.*=all:com.ibm.wsspi.sip*=all:com.ibm.ws.udp.*=all Size= 100

I need com.ibm.websphere.security.*, and com.ibm.ws.ssl.* according to Websphere support documents on this topic.
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
I see what you're asking. I don't believe that we provide a way to turn up those log levels without a root login, but I'll confirm that.
KurtHaserodt
Joined: Nov 12, 2013
Messages: 21
Offline
These levels can be set through the "was set trace" command. The "ce logon" command actually uses the "was set trace" command to do its work.




ce logon
# is the same as
was set trace on

# To see the options available to the "was set" command
was help
.....
set|show|save|edit various parameters
console [on|off] enable/disable outside access to mgmt console
heap MB-value JVM heap size -- deprecated
jvm JVM parameters
ports TCP/UDP-value TLS-value
SIP Container listen ports
pmi none|basic|extended|all
Performance measurement level
sip SIP Container properties
trace on|calls|off|value
Debug/Trace level
verbosegc on|off JVM verbose garbage collection
....

# The form
was set trace value
# is what you want. For your case:

was set trace "*=info:com.ibm.ws.sip.*=all:com.ibm.wsspi.sip*=all:com.ibm.ws.udp.*=all:com.ibm.websphere.security.*=all:com.ibm.ws.ssl.*=all"

# will augment the normal "ce logon" values with the two others about which you asked



MichaelNorman
Joined: Jun 3, 2015
Messages: 448
Offline
Thanks for the info. I used your command to enable additional logging, however nothing new showed up in the log, the same stack trace dump. I also enabled the admin console, and added a couple of parameters to the JVM arguments normally used for troubleshooting this kind of thing, but I do not see any additional entries in ce logv when I did this either. I wonder if this is actually having the desired effect? I restarted the server each time changes were made.

I originally saw that the JVM arguments did not have the https.protocols setting, which by default only TLS1 is supported in Java 7, and our servers do not use TLS1. Is setting these arguments via the console the proper way to modify these settings?


-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -Djavax.net.debug=all
JoelEzell
Joined: Nov 15, 2013
Messages: 780
Offline
Michael, you can specify that you want TLS 1.2 when creating your SecurityContext using SSLUtilityFactory.
Go to:   
Mobile view