2

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.

SoftLover
  • 101
  • 1
  • 12

3 Answers3

3

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;
    }
  • Wouldn't my client start validating a certificate is an issue? As per my understanding, my server(redis) should validate if certification is correct or not. and this is what I mentioned in my Question that I wanted to let Redis validate my certificate rather than implementing "CertificateValidation" – SoftLover Dec 28 '19 at 12:30
1

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)
        {
        }
sadegh salehi
  • 11
  • 1
  • 3
0

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.

Carrick
  • 4,423
  • 3
  • 18
  • 12