How to configure RMI over SSL in ehcache for replication - ssl

I Have ehcache replication working properly without SSL support.
I am looking to support my ehcache replication via SSL i.e. i want to have RMI over SSL
How can i do that?
Here is sample manual peer discovery i am using.
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//10.100.10.12:40002/ssoSessionStore"/>
Can i have some SSL support to RMI call it is doing?
Thanks

I had to change ehcache source code and change few classes to support SSL. As when ehcache over rmi bootsup , it registers itself on rmiregistry. I need to start this registery via SSL context
Look at class RMICacheManagerPeerListener.java for method startRegistry()
This is main class where RMI registry starts. One who is modifying the code needs to understand then ehcache rmi code flow first. Below code is snippet of what has to be done and respectively change other methods.
final String SSL= System.getProperty("isSSL");
protected void startRegistry() throws RemoteException {
try {
LOG.info("Trying to Get Exsisting Registry =========>> ");
if (SSL != null && SSL.equals("ssl"))
registry = LocateRegistry.getRegistry(hostName, port.intValue(),
new SslRMIClientSocketFactory());
else
registry = LocateRegistry.getRegistry(port.intValue());
try {
registry.list();
} catch (RemoteException e) {
// may not be created. Let's create it.
if (SSL != null && SSL.equals("ssl")) {
LOG.info("Registry not found, Creating New SSL =========>> ");
registry = LocateRegistry.createRegistry(port.intValue(),
new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
} else {
LOG.info("Registry not found, Creating New Naming registry =========>> ");
registry = LocateRegistry.createRegistry(port.intValue());
}
registryCreated = true;
}
} catch (ExportException exception) {
LOG.error("Exception starting RMI registry. Error was " + exception.getMessage(), exception);
}
}
Similarly i made change for method
bind()
notifyCacheAdded()
unbind()
disposeRMICachePeer()
populateListOfRemoteCachePeers()
bind()
init()

To patch support for using a custom socket factory you should remove usage of the global defaults. Static method calls on
java.rmi.Naming
should be replaced with the registry returned by the three-argument versions of
LocateRegistry.createRegistry
and
LocateRegistry.getRegistry
and in ConfigurableRMIClientSocketFactory.java change
getConfiguredRMISocketFactory
to return an SSL-based implementation.
See https://gist.github.com/okhobb/4a504e212aef86d4257c69de892e4d7d for an example patch.

Related

How to setup websocket SSL connect using cpprestsdk?

I tried to connect to a websocket server with SSL. But always failed on connection(...).
I am new to cpprestsdk, I can't find doc on how to set SSL information to websocket_client.
websocket_client_config config;
config.set_server_name("wss://host:port/v3/api");
websocket_client client(config);
auto fileStream = std::make_sharedconcurrency::streams::ostream();
pplx::task requestTask = fstream::open_ostream(U("results2.html"))
.then([&](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
uri wsuri(U("wss://host:port/v3/api"));
client.connect(wsuri).wait();
websocket_outgoing_message msg;
msg.set_utf8_message(obj.serialize());
client.send(msg).wait();
printf("send success: %s\n", obj.serialize().c_str());
return client.receive().get();
})
it throws "Error exception:set_fail_handler: 8: TLS handshake failed".
Documentation for cpprestsdk can be found here
C++ REST SDK WebSocket client. Although this doesn't show all the necessary information related to cpprestsdk it will help you.
And also you can get an SSL test example here. I show a simple websocket client implemented using SSL or wss:// scheme
websocket_client client;
std::string body_str("hello");
try
{
client.connect(U("wss://echo.websocket.org/")).wait();
auto receive_task = client.receive().then([body_str](websocket_incoming_message ret_msg) {
VERIFY_ARE_EQUAL(ret_msg.length(), body_str.length());
auto ret_str = ret_msg.extract_string().get();
VERIFY_ARE_EQUAL(body_str.compare(ret_str), 0);
VERIFY_ARE_EQUAL(ret_msg.message_type(), websocket_message_type::text_message);
});
websocket_outgoing_message msg;
msg.set_utf8_message(body_str);
client.send(msg).wait();
receive_task.wait();
client.close().wait();
}
catch (const websocket_exception& e)
{
if (is_timeout(e.what()))
{
// Since this test depends on an outside server sometimes it sporadically can fail due to timeouts
// especially on our build machines.
return;
}
throw;
}
And further examples here to guide you get it successfully is found here
https://github.com/microsoft/cpprestsdk/wiki/Web-Socket

RedisTimeoutException is crashing my aspnet core application

When my application traffic gets high, StackExchange.Redis starts to throw RedisTimeoutException and after some minutes, my asp.net core application crashes.
The Windows event viewer says The process was terminated due to an unhandled exception. Exception Info: StackExchange.Redis.RedisTimeoutException.
Ok, I understand that there is some issue between my app and Redis, but while I can't solve this, how can I prevent the application to shutdown?
Inside startup.cs, I tried to put:
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
eventArgs.Exception.Handle(ex => true);
};
no success....
Any help ?
Tks
How are you creating the ConnectionMultiplexer instances?
Maybe you are not reusing a multiplexer instance and creating a lot of connections.
The ConnectionMultiplexer object should be shared and reused between callers. It is not recommended to create a ConnectionMultiplexer per operation. Check StackExchange.Redis documentation here for more information.
About the exception handling on Asp.NET Core, you can use the UseExceptionHandler diagnostic middleware to handle exceptions globally. Check this article for a complete explanation
Have you tried to put the block that throws the exception in a try/catch block? And perhaps make it try a few times with Polly when there is a timeout. https://github.com/App-vNext/Polly
Normally it shouldn't terminate your app, but since you didn't share any code, We can not be sure.
If you create a service class like below, you can encapsulate all of your redis calls, therefore catch the exceptions.
public class EmptyClass
{
private readonly ConnectionMultiplexer _connectionMultiplexer;
public EmptyClass(ConnectionMultiplexer connectionMultiplexer)
{
_connectionMultiplexer = connectionMultiplexer;
}
public void Execute(Action<ConnectionMultiplexer> action)
{
try
{
action.Invoke(_connectionMultiplexer);
}
catch(RedisTimeoutException ex)
{
}
}
public void TestRun()
{
Execute((ConnectionMultiplexer obj) =>
{
//do stuff with obj.
});
}
}
I agree with #thepirat000's answer, reason is ConnectionMultiplexer
You can use ConnectionMultiplexer according your Redis package (StackExchange.Redis or ServiceStack.Redis) and according your deployment environment
In my aspnet core application (like you) i have used StackExchange.Redis and i have deployed to windows server without any error within below Startup.cs settings
#region Redis settings ConnectionMultiplexer
services.AddDataProtection().ProtectKeysWithDpapi(protectToLocalMachine: true);
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(#"c:\temp-keys"))
.ProtectKeysWithDpapiNG($"CERTIFICATE=HashId:{thumbPrint}", flags: Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None);
services.AddDataProtection().ProtectKeysWithDpapiNG();
services.Configure<StorageConfiguration>(new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build());
var redisConf = Configuration.GetSection("RedisConnection").Get<RedisConnection>();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(redisConf.Host.ToString() + ":" + redisConf.Port.ToString());
services.AddDataProtection().PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(redisConf.Host.ToString() + ":" + redisConf.Port.ToString()));
#endregion
Look here for basic usage https://stackexchange.github.io/StackExchange.Redis/Basics.html

Add Proxy to restlet ClientRessource

I am trying to add proxy settings to a Java Swing client app, which connects and gets data over https from an external server. However the ClientResource (restlet:2.4.0) ignores all efforts with parameters and connects directly to the url? If the syntax is correct, what are the correct parameters?
Further, how can I use system proxy settings?
private static ClientResource getClientResource(String url) {
ClientResource clientResource = null;
try {
// test
Client client = new Client(new Context(), Protocol.HTTPS);
client.getContext().getParameters().add("https.proxyHost", "PROXY_IP");
client.getContext().getParameters().add("https.proxyPort", "PROXY_PORT");
clientResource = new ClientResource(url);
// test
clientResource.setNext(client);
} catch (Exception e) {
e.printStackTrace();
}
return clientResource;
}
private static Response sendGetRequest(String url) {
ClientResource resource = getClientResource(BASE_URL + url);
try {
resource.get();
} catch (ResourceException e){
e.printStackStrace();
return null;
}
return getResponse();
}
EDIT added compiles:
compile 'org.restlet.jse:org.restlet:2.3.12'
compile 'org.restlet.jse:org.restlet.ext.jackson:2.3.12'
// switch to Apache Http Client, enable proxy'
compile 'org.restlet.jse:org.restlet.ext.httpclient:2.3.12'
// httpClient for Class Definitions
compile 'org.apache.httpcomponents:httpclient:4.3'
CURRENT EXCEPTION:
Starting the Apache HTTP client
An error occurred during the communication with the remote HTTP server.
org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.restlet.ext.httpclient.internal.HttpMethodCall.sendRequest(HttpMethodCall.java:339)
at org.restlet.engine.adapter.ClientAdapter.commit(ClientAdapter.java:105)
at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:119)
at org.restlet.Client.handle(Client.java:153)
I think this is only supported with the httpClient extension, that relies on the Apache HTTP client library (maven artifact id: org.restlet.ext.httpclient).
You can then either use the system environment properties: http.proxyHost and http.proxyPort, or set these parameters on the client instance (as you did, but names are distinct and documented here ).
Client client = new Client(new Context(), Protocol.HTTPS);
client.getContext().getParameters().add("proxyHost", "PROXY_IP");
client.getContext().getParameters().add("proxyPort", "PROXY_PORT");

Sending Text Message using JMS on glassfish server

I am testing JMS with glassfish server so for that i want to send simple text message on glassfish server queue. I have tried with ActiveMQ and that is going fine but i unable to understand what can i put in configuration jndi.properties file and which jar is needed for glassfish server. Please give me some idea to implement this.
thanks in advance
Since you're using Glassfish, the easiest way is to write simple application (EJB) that will perform the task. You have to define in GF:
ConnectionFactory (Resources -> JMS Resources -> Connection Factory),
let's give it JNDI name jms/ConnectionFactory
Message queue (Resources -> JMS Resources -> Destination Resources),
let's give it JNDI name jms/myQueue
Next step is to use these in some EJB that you need to write. It's not hard: firstly, you have to inject:
#Resource(mappedName="jms/ConnectionFactory")
private ConnectionFactory cf;
#Resource(mappedName="jms/myQueue")
private Queue messageQueue;
and then use it like this:
..
javax.jms.Connection conn = null;
javax.jms.Session s = null;
javax.jms.MessageProducer mp = null
try {
conn = cf.createConnection();
s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
mp = s.createProducer(messageQueue);
javax.jms.TextMessage msg = s.createTextMessage();
msg.setStringProperty("your-key", "your-value");
msg.setText("Your text message");
mp.send(msg);
}
catch(JMSException ex) {
// exception handling
}
finally {
try {
// close Connection, Session and MessageProducer
} catch (JMSException ex) {
//exception handling
}
}
Regarding configuration, you don't need any external JAR, everything that is needed is shipped. If you don't want to write EJB, but regular Java (standalone) application, then you'll have to include jms.jar and imq.jar.

Tomcat 7.0.14 LDAP authentication

I have a web application running on Tomcat 7.0.14 and I'm using LDAP for user authentication. The problem is that when a user logs in after an inactive period the following warning comes out. The inactive period doesn't have to be long, as only few minutes is enough. However, the user is able to log in despite of the warning. From the users' point of view the application behaves normally, but Tomcat log reveals the warning below.
Jun 6, 2012 9:41:19 AM org.apache.catalina.realm.JNDIRealm authenticate
WARNING: Exception performing authentication
javax.naming.CommunicationException [Root exception is java.io.IOException: connection closed]; remaining name ''
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:157)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2685)
at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2593)
at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2567)
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1932)
at com.sun.jndi.ldap.LdapCtx.doSearchOnce(LdapCtx.java:1924)
at com.sun.jndi.ldap.LdapCtx.c_getAttributes(LdapCtx.java:1317)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:231)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:139)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:127)
at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:140)
at org.apache.catalina.realm.JNDIRealm.bindAsUser(JNDIRealm.java:1621)
at org.apache.catalina.realm.JNDIRealm.checkCredentials(JNDIRealm.java:1480)
at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:1131)
at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:1016)
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:282)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:440)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Caused by: java.io.IOException: connection closed
at com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1576)
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:155)
... 27 more
The LDAP configuration is in the application's context.xml file:
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionURL="ldaps://ldap-company.com"
userPattern="uid={0},dc=company,dc=com"
roleBase="ou=groups,o=company"
roleName="uid"
roleSearch="uniqueMember={0}"
roleSubtree="true" />
I've found posts about this problem from several forums, but no one seems to have figured out the solution.
I was able to figure out the reason for the warning and also a way to get rid of it.
The reason for the warning was that the LDAP server is closing all the connections that have been idle for more than 5 minutes. The LDAP server admin told me that it's recommended to close the connection immediately after each login request, because the number of available handles is limited. Tomcat's JNDIRealm, however, doesn't offer a way to configure this, so I resolved the problem by extending the JNDIRealm class and overriding the authenticate(..) method. All that needs to be done is to close the connection to the LDAP server after each authentication request and the warnings are gone.
Note that the package needs to be the same as JNDIRealm class, because otherwise it's not possible to access the context variable.
package org.apache.catalina.realm;
import java.security.Principal;
public class CustomJNDIRealm extends JNDIRealm {
#Override
public Principal authenticate(String username, String credentials) {
Principal principal = super.authenticate(username, credentials);
if (context != null) {
close(context);
}
return principal;
}
}
Generated jar needs to be put under Tomcat's lib folder and change the className in the application's context.xml to org.apache.catalina.realm.CustomJNDIRealm. Then just restart Tomcat and that's it.
<Realm className="org.apache.catalina.realm.CustomJNDIRealm"
connectionURL="ldaps://ldap-company.com"
userPattern="uid={0},dc=company,dc=com"
roleBase="ou=groups,o=company"
roleName="uid"
roleSearch="uniqueMember={0}"
roleSubtree="true" />
I am answering, because this is a current research topic for me, as we currently extend the JNDIRealm for our needs.
The realm will retry after the warning, so the suggested patch is just beautifying the logfile. Later versions of tomcat (7.0.45 iirc) will beautify the logmessage to make clear, that there is a retry attempt done.
If you want to have the realm doing authentication with a fresh connection every time, it should be sufficient to use this class (I have not tested this implementation but will if our realm is done):
package org.apache.catalina.realm;
import java.security.Principal;
public class CustomJNDIRealm extends JNDIRealm {
#Override
public Principal authenticate(String username, String credentials) {
Principal principal = null;
DirContext context = null;
try {
context = open();
principal = super.authenticate(context, username, credentials);
}
catch(Throwable t) {
// handle errors
principal = null;
}
finally {
close(context); // JNDIRealm close() takes care of null context
}
return principal;
}
#Override
protected DirContext open() throws NamingException {
// do no longer use the instance variable for context caching
DirContext context = null;
try {
// Ensure that we have a directory context available
context = new InitialDirContext(getDirectoryContextEnvironment());
} catch (Exception e) {
connectionAttempt = 1;
// log the first exception.
containerLog.warn(sm.getString("jndiRealm.exception"), e);
// Try connecting to the alternate url.
context = new InitialDirContext(getDirectoryContextEnvironment());
} finally {
// reset it in case the connection times out.
// the primary may come back.
connectionAttempt = 0;
}
return (context);
}
}
The LDAP server is disconnecting idle connections that have been idle, that is, no requests transmitted, after a certain period of time.
basically adding a keepaliveTimeout to override connection timeout which was around 5 minutes resolved the issue in my scenario i.e. keepaliveTimeout ="-1" attribute to connector element in server.xml file
keepAliveTimeout="-1"