Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis Cloud Connection Example #98

Merged
merged 44 commits into from
May 2, 2023
Merged

Redis Cloud Connection Example #98

merged 44 commits into from
May 2, 2023

Conversation

shacharPash
Copy link
Contributor

Closes #96

@shacharPash shacharPash temporarily deployed to REDIS_USER March 27, 2023 13:21 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER March 27, 2023 13:21 — with GitHub Actions Inactive
@codecov-commenter
Copy link

codecov-commenter commented Mar 27, 2023

Codecov Report

Patch and project coverage have no change.

Comparison is base (a39b818) 93.27% compared to head (ad11e0b) 93.27%.

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files
@@           Coverage Diff           @@
##           master      #98   +/-   ##
=======================================
  Coverage   93.27%   93.27%           
=======================================
  Files          77       77           
  Lines        4582     4582           
  Branches      424      424           
=======================================
  Hits         4274     4274           
  Misses        186      186           
  Partials      122      122           

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@shacharPash shacharPash temporarily deployed to REDIS_USER March 27, 2023 14:26 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER March 27, 2023 14:26 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER March 29, 2023 09:57 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER March 29, 2023 09:57 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER April 2, 2023 13:11 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER April 2, 2023 13:11 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER April 4, 2023 12:36 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER April 4, 2023 12:36 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER April 4, 2023 19:28 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER April 4, 2023 19:28 — with GitHub Actions Inactive
@slorello89
Copy link
Member

@shacharPash - this will still break until the .pem/.crt/.key file are all deployed along side the binary (you might need to do a cURL to the appropriate spots the test runner executes from tests/NRedisStack.Tests/bin/Debug/net6.0 (substitute net6.0 with chosen test framework). But the tests I modified/added will work as an example.

In a real-world scenario you would NOT be building your own certificate chain in your program, rather certificates would be managed by the admin responsible for overseeing the machine and either installed with GPO on windows, your keychain on mac, or pick your flavor of cert-store on Linux.

There are several steps here:

  1. Import the client's certificate:
var redisUserCertificate = new X509Certificate2(File.ReadAllBytes(redisUserCrtPath));
  1. Import private key for client to sign it's cert with:
var redisUserPrivateKeyText = File.ReadAllText(redisUserPrivateKeyPath);
var pemFileData = File.ReadAllLines(redisUserPrivateKeyPath).Where(x => !x.StartsWith("-"));
var binaryEncoding = Convert.FromBase64String(string.Join(null, pemFileData));

rsa.ImportRSAPrivateKey(binaryEncoding, out _);
redisUserCertificate.CopyWithPrivateKey(rsa);
rsa.ImportFromPem(redisUserPrivateKeyText.ToCharArray());
var clientCert = redisUserCertificate.CopyWithPrivateKey(rsa);
  1. Import ca cert:
var redisCaCertificate = new X509Certificate2(File.ReadAllBytes(redisCaPath));
  1. When the server's certificate fails to validate (which of course it will because it's a self-signed cert that you haven't registered with your machine as a trusted root CA) you need to build your own chain to validate, then check the server cert to make sure that it's groks with the newly established chain, tossing anything where the only complaint is that the root CA isn't a trusted root (we are telling it what authority to draw from):
(_, cert, _, errors) =>
            {
                if (errors == SslPolicyErrors.None)
                {
                    return true;
                }

                var privateChain = new X509Chain();
                privateChain.ChainPolicy = new X509ChainPolicy { RevocationMode = X509RevocationMode.NoCheck };
                X509Certificate2 cert2 = new X509Certificate2(cert!);
                privateChain.ChainPolicy.ExtraStore.Add(redisCaCertificate);
                privateChain.Build(cert2);
                
                bool isValid = true;

                // we're establishing the trust chain so if the only complaint is that that the root CA is untrusted, and the root CA root
                // matches our certificate, we know it's ok
                foreach (X509ChainStatus chainStatus in privateChain.ChainStatus.Where(x=>x.Status != X509ChainStatusFlags.UntrustedRoot))
                {
                    if (chainStatus.Status != X509ChainStatusFlags.NoError)
                    {
                        isValid = false;
                        break;
                    }
                }

                return isValid;
            }

The logic is equivalent regardless of which method you use, you just use slightly different components of the configuration.

@slorello89
Copy link
Member

Btw @chayim - is the instance we're pointing to here shared for doing TLS validation across the other peer clients? From what I can tell they are all just using a specially spun up TLS enabled version for Redis?

@shacharPash shacharPash temporarily deployed to REDIS_USER April 13, 2023 08:02 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER April 13, 2023 08:02 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER May 1, 2023 08:55 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER May 1, 2023 08:55 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER May 1, 2023 11:44 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER May 1, 2023 11:44 — with GitHub Actions Inactive
@slorello89 slorello89 force-pushed the Issue96/TlsExample branch from f450a89 to e646964 Compare May 1, 2023 12:39
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:39 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:39 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:52 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:52 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:59 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 12:59 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 13:15 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 13:15 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 13:24 — with GitHub Actions Inactive
@slorello89 slorello89 temporarily deployed to REDIS_USER May 1, 2023 13:24 — with GitHub Actions Inactive
@slorello89
Copy link
Member

Fixed the .NET Framework examples.

Pre .NET Core 3.1 this was a very manual process where you had to interact with openSSL almost directly via bouncy-castle. It looks like a later version of Bouncy Castle might have changed the types it was bubbling back up from when the now very old examples you'd find online were created. After making those couple of adjustments, and re-exporting the cert each time, and trimming the key (it was getting pulled in with an extra newline or whitespace or something - this all works now.

@chayim chayim marked this pull request as ready for review May 2, 2023 06:13
@shacharPash shacharPash temporarily deployed to REDIS_USER May 2, 2023 11:48 — with GitHub Actions Inactive
@shacharPash shacharPash temporarily deployed to REDIS_USER May 2, 2023 11:48 — with GitHub Actions Inactive
@shacharPash shacharPash merged commit e269de5 into master May 2, 2023
@shacharPash shacharPash deleted the Issue96/TlsExample branch May 2, 2023 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add TLS example with "production-ready" options.CertificateValidation and test it in CI against Redis Cloud
4 participants