How to configure camel jetty producer endpoint to use SSL certificate - ssl

Camel jetty endpoint allows several SSL options, but only applicable to consumer (i.e. server side). See Apache Camel Jetty
Is there a way to force the producer to use the certificate without writing a bunch of codes? The remote server requires client authentication.

Looks like coding is the only option. There are two choices that I've tried: configure SSL to (1) JettyComponent or (2) https4 component.
def configJetty = {
println("Configuring Jetty component...")
val ksp = new KeyStoreParameters()
ksp.setResource(keyStore)
ksp.setPassword(keyPassword)
val kmp = new KeyManagersParameters()
kmp.setKeyStore(ksp)
kmp.setKeyPassword(keyPassword)
val scp = new SSLContextParameters()
scp.setKeyManagers(kmp)
val jettyComponent = camelContext.getComponent("jetty").asInstanceOf[JettyHttpComponent]
jettyComponent.setSslContextParameters(scp)
}
Or
def configHttps4 = {
println("Configuring HTTPS4 component...")
val ksp = new KeyStoreParameters()
ksp.setResource(keyStore)
ksp.setPassword(keyPassword)
val tsp = new KeyStoreParameters()
tsp.setResource(trustStore)
tsp.setPassword(trustPassword)
val kmp = new KeyManagersParameters()
kmp.setKeyStore(ksp)
kmp.setKeyPassword(keyPassword)
val tmp = new TrustManagersParameters()
tmp.setKeyStore(tsp)
val scp = new SSLContextParameters()
scp.setKeyManagers(kmp)
scp.setTrustManagers(tmp)
val httpComponent = camelContext.getComponent("https4").asInstanceOf[HttpComponent]
httpComponent.setSslContextParameters(scp)
}
Then the endpoint URL can be:
https4://somewhere.com
or
jetty:https://somewhere.com
Note: with the above code, jetty component won't be able to speak clear HTTP anymore.

Related

How do i Bulk Load AWS Neptune using a Lambda?

I'm trying to attempt bulk loading Neptune using the loader endpoint, and Apache HTTP client by making the POST call like below.
My lambda is in the same VPC as Neptune and has the same sub-nets and Security group as well.
However i'm seeing :
`org.apache.http.NoHttpResponseException: cluster-endpoint-url:8182 failed to respond`
ObjectMapper objectMapper = new ObjectMapper();
String requestBodyJSON = objectMapper
.writeValueAsString(values);
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://endpont:8182/loader");
log.info("Initiated HTTP Client ");
HttpEntity stringEntity = new StringEntity(requestBodyJSON, ContentType.APPLICATION_JSON);
httpPost.setEntity(stringEntity);
CloseableHttpResponse response2 = httpclient.execute(httpPost);
log.info("RESPONSE is "+ response2);
The likely issue is the use of http:// versus https://. Neptune does not allow for non-SSL/TLS connections. Also check your security group configuration. The security group for Neptune should be allowing inbound traffic from the subnets or the security group used by the Lambda function.

GRPC Okhttp android client channel with self signed ssl certificate

I have a grpc-js server using self signed ssl certificates.
var credentials = grpc.ServerCredentials.createSsl(
fs.readFileSync('./node/grpc/ssl/ca.crt'),
[{
cert_chain: fs.readFileSync('./node/grpc/ssl/server.crt'),
private_key: fs.readFileSync('./node/grpc/ssl/server.key')
}],
true
);
I then tested this setup with a grpc-js client with the following credential setup and this works.
var credentials = grpc.credentials.createSsl(
fs.readFileSync('./node/grpc/ssl/ca.crt'),
fs.readFileSync('./node/grpc/ssl/client.key'),
fs.readFileSync('./node/grpc/ssl/client.crt')
);
I want to replicate this in Android using OkHttpChannelBuilder but it is a bit more complicated. This is what I have so far.
private val mChannel : ManagedChannel
init {
/**
* Server certificate to make it trusted.
*/
val serverCrtFile = applicationContext.resources.openRawResource(R.raw.server)
val serverCertificate: X509Certificate =
CertificateFactory.getInstance("X.509").generateCertificate(serverCrtFile) as X509Certificate
val caKeyStore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
load(null, null)
setCertificateEntry("server", serverCertificate)
}
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
init(caKeyStore)
}
val sslContext = SSLContext.getInstance("TLS").apply {
init(null, trustManagerFactory.trustManagers, null)
}
mChannel = OkHttpChannelBuilder
.forAddress(BuildConfig.GRPC_HOST_ADDRESS, BuildConfig.GRPC_HOST_PORT)
.sslSocketFactory(sslContext.socketFactory)
.keepAliveTime(10, TimeUnit.SECONDS)
.useTransportSecurity()
.keepAliveWithoutCalls(true)
.build()
}
Everything worked before implementing ssl (so using plaintext() on the channel builder).
The error I get now is io.grpc.StatusRuntimeException: UNAVAILABLE: End of stream or IOException.
Can someone please tell me if I am doing something wrong and how I can get a successful connection like between the js server and client.
Looks like the SSL handshake failed on the server side so it will be helpful to get server side detailed logs to see what went wrong.
One possibility is using KeyStore.getInstance. Can you try using "PKCS12"?
KeyStore.getInstance("PKCS12")

Amazon Secrets Manager, Java 7, and CipherSuites

I am trying to get AWS Secrets Manager to work on an older Java 7 platform. Unfortunately we're locked on Java 7 for now.
The issue I have is that Java 7 had some security issues with SSL, and most modern Java platforms are using newer cipherSuites. Thus I get the error
javax.net.ssl.SSLHandshakeException: No negotiable cipher suite
In other interfaces I've been able to solve the issue by doing an .setEnabledCipherSuites on the SSL socket.
The problem here is that the Secrets Manager client does not expose the socket (AFAICT), nor does it expose the SocketFactory. I've been trying to create a new SSLContext wrapping the stock SSLContext that will provide a custom SocketFactory but creating and installing a custom SSLContext has proven to be quite complicated.
Before I end up pulling out the rest of my hair, is there an easier way to do this?
AWS Secrets Manager uses Apache HTTP Client (httpclient-4.5.7) under the covers. Is there a static way of hooking the Apache client with a custom Socket, SocketFactory, or SSLContext? One that does not require access to the HTTPClient object (which is not exposed either).
After much head banging I came up with the following code:
final String ciphers[] =
{ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA256" };
final String[] protocols = new String[]
{ "TLSv1.2" };
// create and initialize an SSLContext for a custom socket factory
final SSLContext sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, null, new SecureRandom());
// and here's our SocketFactory
final SSLConnectionSocketFactory secureSocketFactory = new SSLConnectionSocketFactory(sslcontext, protocols,
ciphers, new DefaultHostnameVerifier());
// Create a custom AWS Client Configuration with our socket factory
final ClientConfiguration cc = new ClientConfiguration();
final ApacheHttpClientConfig acc = cc.getApacheHttpClientConfig();
acc.setSslSocketFactory(secureSocketFactory);
// Create a Secrets Manager client with our custom AWS Client Configuration
final AWSSecretsManager client = AWSSecretsManagerClientBuilder //
.standard() //
.withRegion(region) //
.withClientConfiguration(cc) //
.build();
client is then used for the requests.

Connecting to Mule's JMX output from Java

What is the standard way to connect to Mules JMX output through a standard java program,
I'm trying something like this but looking at the source of Mules SimplePasswordJmxAuthenticator, I need to supply auth tokens to mule so perhaps there is a better lib to use for sending jmx requests?
url1 = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1198/server");
JMXConnector jmxc = JMXConnectorFactory.connect(url1);
I'm not familiar with the details of Mule's JMX server, but here's how you could add credentials to your code snippet:
url1 = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1198/server");
String[] credentials = new String[]{"myusername", "mypassword"};
Map<String, Object> env = new HashMap<String, Object>(1);
env.put(javax.management.remote.JMXConnector.CREDENTIALS, credentials);
JMXConnector jmxc = JMXConnectorFactory.connect(url1, env);
That's the standard JMXRemoting way of doing it. Perhaps it will work for you.

How can I configure Apache HttpClient 4.x to use a specific Websphere SSL alias?

We have an issue in our environment when using Websphere to attempt to connect to an external system with HttpClient 4.x (current version is 4.2.1). Connecting to the external system is fine with their certificate being installed in Websphere with no additional configuration of HttpClient. However, when they enabled mutual authentication, it no longer works and we get a SSLPeerUnverifiedException exception:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated,
at com.ibm.jsse2.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:105),
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128),
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572),
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180),
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294),
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640),
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479),
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906),
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1066),
I was provided the following code sample, and I was wondering if there's any way to configure HttpClient to use an explicit alias like this code sample does. I've tried to find good documentation on using SSL mutual authentication with HttpClient 4 and haven't been able to find much.
Here's the code sample:
private HttpURLConnection getConnection(String server, String machine,
String port) throws Exception {
URL u = new URL(server);
HttpsURLConnection connection = (HttpsURLConnection) u.openConnection();
String alias = "CellDefaultSSLSettings";
final HashMap connectionInfo = new HashMap();
connectionInfo.put(JSSEHelper.CONNECTION_INFO_DIRECTION,
JSSEHelper.DIRECTION_OUTBOUND);
connectionInfo.put(JSSEHelper.CONNECTION_INFO_REMOTE_HOST, machine);
connectionInfo.put(JSSEHelper.CONNECTION_INFO_REMOTE_PORT, port);
javax.net.ssl.SSLSocketFactory sslFact = JSSEHelper.getInstance()
.getSSLSocketFactory(alias, connectionInfo, null);
connection.setSSLSocketFactory(sslFact);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
return connection;
}
Basically, how do I make HttpClient use "CellDefaultSSLSettings"?
Fundamentally this problem has nothing to do with HttpClient. HttpClient can be configured to establish HTTPS connections using any custom SSLContext or SSLSocketFactory instance. This is basically about how to use JSSE APIs to configure SSLContext in the right way. In your particular case JSSEHelper does all the hard work for you.
// JSSE socket factory
javax.net.ssl.SSLSocketFactory jssesf = JSSEHelper.getInstance().getSSLSocketFactory(alias, connectionInfo, null);
// HC socket factory
SSLSocketFactory hcsf = new SSLSocketFactory(jssesf, SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
This will give a connection socket factory that can be registered with the connection manager.
HttpClient 4.3 also comes with SSLContextBuilder class which can be used to assemble custom SSL configurations using fluid builder API.
https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContextBuilder.java
oleg's answer helped me out.
What I did was extend the DefaultHttpClient, and each constructor takes a String argument for the destination URL and calls a method setupScheme:
private void setupScheme(final String url) throws Exception {
Scheme scheme = new Scheme("https", 443, retrieveWebsphereSSLConnectionFactory(url));
getConnectionManager().getSchemeRegistry().register(scheme);
}
The method retrieveWebsphereSSLConnectionFactory essentially combines the code from the sample with the code oleg provided:
private SchemeSocketFactory retrieveWebsphereSSLConnectionFactory(final String url)
throws SSLException, URISyntaxException {
final String alias = "CellDefaultSSLSettings";
final HashMap<String, String> connectionInfo = new HashMap<String, String>();
connectionInfo.put(JSSEHelper.CONNECTION_INFO_DIRECTION, JSSEHelper.DIRECTION_OUTBOUND);
connectionInfo.put(JSSEHelper.CONNECTION_INFO_REMOTE_HOST,
URIUtils.extractHost(new URI(url)).getHostName());
connectionInfo.put(JSSEHelper.CONNECTION_INFO_REMOTE_PORT, "443");
return new SSLSocketFactory(JSSEHelper.getInstance().getSSLSocketFactory(alias, connectionInfo, null),
SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}