SoftLover
SoftLover

Reputation: 101

SSL connectivity to Redis with StackExchange.Redis

I am having a very weird issue with StackExchange.Redis to connect with Redis.

I have enabled SSL on Redis database and I am not able to connect from client to Redis server with SSL certificate with below code.

  static RedisConnectionFactory()
        {
            try
            {
                string connectionString = "rediscluster:13184";
                var options = ConfigurationOptions.Parse(connectionString);
                options.Password = "PASSWORD";
                options.AllowAdmin = true;
                options.AbortOnConnectFail = false;
                options.Ssl = true;
                options.SslHost = "HOSTNAME";
                var certificate = GetCertificateFromThubprint();
                options.CertificateSelection += delegate
                {
                    return certificate;
                };

                Connection = new Lazy<ConnectionMultiplexer>(
               () => ConnectionMultiplexer.Connect(options)
                );
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to connect to Cache Server " + ex);
            }

        }

        public static ConnectionMultiplexer GetConnection() => Connection.Value;

        public static IEnumerable<RedisKey> GetCacheKeys()
        {

            return GetConnection().GetServer("rediscluster", 13184).Keys();
        }

        // Find certificate based on Thumbprint
        private static X509Certificate2 GetCertificateFromThubprint()
        {
  // Find certificate from "certificate store" based on thumbprint and return
StoreName CertStoreName = StoreName.Root;
            string PFXThumbPrint = "NUMBER";
            X509Store certLocalMachineStore = new X509Store(CertStoreName, StoreLocation.LocalMachine);
            certLocalMachineStore.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certLocalMachineCollection = certLocalMachineStore.Certificates.Find(
                                       X509FindType.FindByThumbprint, PFXThumbPrint, true);
            certLocalMachineStore.Close();
 return certLocalMachineCollection[0];
       }

However, If I create a console application and connect to Redis with above code then I am able to connect, but If I used same code from my web application to connect to redis then I am not able to connect.

Not sure if I am missing something.

Also, I went through "mgravell" post

In that post he has configured "CertificateValidation" method, In my scenario I want Redis to validate SSL certificate. so I have not implementation validation. And implemented "CertificateSelection" method to provide client certificate.

Upvotes: 2

Views: 15218

Answers (3)

sadegh salehi
sadegh salehi

Reputation: 37

I was able to ssl the Redis server I had started on a VM with the following codes. add stackexchange.redis visual studio

            try
        {
            ConfigurationOptions configurationOptions = new ConfigurationOptions
            {
                KeepAlive = 0,
                AllowAdmin = true,
                EndPoints = { { "SERVER IP ADDRESS", 6379 }, { "127.0.0.1", 6379 } },
                ConnectTimeout = 5000,
                ConnectRetry = 5,
                SyncTimeout = 5000,
                AbortOnConnectFail = false,
            };
            configurationOptions.CertificateSelection += delegate
            {
                var cert = new X509Certificate2("PFX FILE PATH", "");
                return cert;
            };
            ConnectionMultiplexer connection =
                  ConnectionMultiplexer.Connect(configurationOptions);
            IDatabase databaseCache = connection.GetDatabase();
            //set value
            databaseCache.StringSet("KEYNAME", "KEYVALUE");
            //get Value
            label_show_value.Text = databaseCache.StringGet("KEYNAME").ToString();
        }
        catch (Exception e1)
        {
        }

Upvotes: 1

Carrick
Carrick

Reputation: 4543

In cases like this where you are using a client certificate and it works in a console app but does not work for some other application (you don't say but I guess from an IIS hosted web app), it almost always has to do with whether the account has permission to access the private key.

The console app runs with your account which probably has access to the private key.

To give an account access

  1. open the Local Computer certificate store
  2. find your client certificate
  3. right click and choose "All tasks -> Manage Provate Keys..."
  4. click "Add..." and add the account.

Note: if your adding an IIS App Pool account the format is: IIS APPPOOL<my app pool name>

Location should be the local machine and not a domain.

Upvotes: 0

Arkhangelskiy Evgeniy
Arkhangelskiy Evgeniy

Reputation: 622

You can try to validate the cert using CertificateValidation. I tried the following code and it worked for me:

options.CertificateValidation += ValidateServerCertificate;

...

public static bool ValidateServerCertificate(
        object sender,
        X509Certificate certificate,
        X509Chain chain,
        SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        return false;
    }

Upvotes: 3

Related Questions