Example #1
0
        public string SetupEncryptedDatabase(out TestCertificatesHolder certificates, out byte[] masterKey, [CallerMemberName] string caller = null)
        {
            certificates = _parent.Certificates.SetupServerAuthentication();
            var dbName = _parent.GetDatabaseName(caller);

            _parent.Certificates.RegisterClientCertificate(certificates, new Dictionary <string, DatabaseAccess>(), SecurityClearance.ClusterAdmin);

            string base64Key = CreateMasterKey(out masterKey);

            EnsureServerMasterKeyIsSetup(_parent.Server);

            _parent.Server.ServerStore.PutSecretKey(base64Key, dbName, true);
            return(dbName);
        }
Example #2
0
        public void EncryptedCluster(List <RavenServer> nodes, TestCertificatesHolder certificates, out string databaseName)
        {
            databaseName = _parent.GetDatabaseName();

            foreach (var node in nodes)
            {
                _parent.Certificates.RegisterClientCertificate(certificates, new Dictionary <string, DatabaseAccess>(), SecurityClearance.ClusterAdmin, node);

                var base64Key = CreateMasterKey(out _);

                EnsureServerMasterKeyIsSetup(node);

                Assert.True(node.ServerStore.EnsureNotPassiveAsync().Wait(TimeSpan.FromSeconds(30)));                                                                // activate license so we can insert the secret key
                Assert.True(node.ServerStore.LicenseManager.TryActivateLicenseAsync(_parent.Server.ThrowOnLicenseActivationFailure).Wait(TimeSpan.FromSeconds(30))); // activate license so we can insert the secret key

                node.ServerStore.PutSecretKey(base64Key, databaseName, overwrite: true);
            }
        }
Example #3
0
        public string EncryptedServer(out TestCertificatesHolder certificates, out string databaseName)
        {
            certificates = _parent.Certificates.SetupServerAuthentication();
            databaseName = _parent.GetDatabaseName();
            _parent.Certificates.RegisterClientCertificate(certificates, new Dictionary <string, DatabaseAccess>(), SecurityClearance.ClusterAdmin);

            var buffer = new byte[32];

            using (var rand = RandomNumberGenerator.Create())
            {
                rand.GetBytes(buffer);
            }

            var base64Key = Convert.ToBase64String(buffer);

            var canUseProtect = PlatformDetails.RunningOnPosix == false;

            if (canUseProtect)
            {
                // sometimes when using `dotnet xunit` we get platform not supported from ProtectedData
                try
                {
#pragma warning disable CA1416 // Validate platform compatibility
                    ProtectedData.Protect(Encoding.UTF8.GetBytes("Is supported?"), null, DataProtectionScope.CurrentUser);
#pragma warning restore CA1416 // Validate platform compatibility
                }
                catch (PlatformNotSupportedException)
                {
                    canUseProtect = false;
                }
            }

            if (canUseProtect == false) // fall back to a file
            {
                _parent.Server.ServerStore.Configuration.Security.MasterKeyPath = _parent.GetTempFileName();
            }

            Assert.True(_parent.Server.ServerStore.EnsureNotPassiveAsync().Wait(TimeSpan.FromSeconds(30)));                                                                // activate license so we can insert the secret key
            Assert.True(_parent.Server.ServerStore.LicenseManager.TryActivateLicenseAsync(_parent.Server.ThrowOnLicenseActivationFailure).Wait(TimeSpan.FromSeconds(30))); // activate license so we can insert the secret key
            _parent.Server.ServerStore.PutSecretKey(base64Key, databaseName, overwrite: true);

            return(Convert.ToBase64String(buffer));
        }
Example #4
0
        protected Dictionary<string, string> GetServerSettingsForPort(bool useSsl, out string serverUrl, out TestCertificatesHolder certificates)
        {
            var customSettings = new Dictionary<string, string>();

            if (useSsl)
            {
                serverUrl = UseFiddlerUrl("https://127.0.0.1:0");
                certificates = SetupServerAuthentication(customSettings, serverUrl);
            }
            else
            {
                serverUrl = UseFiddlerUrl("http://127.0.0.1:0");
                customSettings[RavenConfiguration.GetKey(x => x.Core.ServerUrls)] = serverUrl;
                certificates = null;
            }

            return customSettings;
        }
Example #5
0
        protected async Task<(List<RavenServer> Nodes, RavenServer Leader, TestCertificatesHolder Certificates)> CreateRaftClusterInternalAsync(
            int numberOfNodes,
            bool? shouldRunInMemory = null,
            int? leaderIndex = null,
            bool useSsl = false,
            IDictionary<string, string> customSettings = null,
            List<IDictionary<string, string>> customSettingsList = null,
            bool watcherCluster = false,
            [CallerMemberName] string caller = null)
        {
            string[] allowedNodeTags = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
            var actualLeaderIndex = leaderIndex;
            leaderIndex ??= _random.Next(0, numberOfNodes);
            RavenServer leader = null;
            var serversToPorts = new Dictionary<RavenServer, string>();
            var clusterNodes = new List<RavenServer>(); // we need this in case we create more than 1 cluster in the same test

            _electionTimeoutInMs = Math.Max(300, numberOfNodes * 80);

            if (customSettingsList != null && customSettingsList.Count != numberOfNodes)
            {
                throw new InvalidOperationException("The number of custom settings must equal the number of nodes.");
            }

            TestCertificatesHolder certificates = null;

            for (var i = 0; i < numberOfNodes; i++)
            {
                if (customSettingsList == null)
                {
                    customSettings ??= new Dictionary<string, string>(DefaultClusterSettings)
                    {
                        [RavenConfiguration.GetKey(x => x.Cluster.ElectionTimeout)] = _electionTimeoutInMs.ToString(),
                    };
                }
                else
                {
                    customSettings = customSettingsList[i];
                }

                string serverUrl;

                if (useSsl)
                {
                    serverUrl = UseFiddlerUrl("https://127.0.0.1:0");
                    certificates = SetupServerAuthentication(customSettings, serverUrl);
                }
                else
                {
                    serverUrl = UseFiddlerUrl("http://127.0.0.1:0");
                    customSettings[RavenConfiguration.GetKey(x => x.Core.ServerUrls)] = serverUrl;
                }
                var co = new ServerCreationOptions
                {
                    CustomSettings = customSettings,
                    RunInMemory = shouldRunInMemory,
                    RegisterForDisposal = false,
                    NodeTag = allowedNodeTags[i]
                };
                var server = GetNewServer(co, caller);
                var port = Convert.ToInt32(server.ServerStore.GetNodeHttpServerUrl().Split(':')[2]);
                var prefix = useSsl ? "https" : "http";
                serverUrl = UseFiddlerUrl($"{prefix}://127.0.0.1:{port}");
                Servers.Add(server);
                clusterNodes.Add(server);

                serversToPorts.Add(server, serverUrl);
                if (i == leaderIndex)
                {
                    await server.ServerStore.EnsureNotPassiveAsync(null, nodeTag: co.NodeTag);
                    leader = server;
                }
            }

            using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5)))
            {
                for (var i = 0; i < numberOfNodes; i++)
                {
                    if (i == leaderIndex)
                    {
                        continue;
                    }
                    var follower = clusterNodes[i];
                    // ReSharper disable once PossibleNullReferenceException
                    leader = await ActionWithLeader(l =>
                        l.ServerStore.AddNodeToClusterAsync(serversToPorts[follower], nodeTag: allowedNodeTags[i], asWatcher: watcherCluster, token: cts.Token), clusterNodes);
                    if (watcherCluster)
                    {
                        await follower.ServerStore.WaitForTopology(Leader.TopologyModification.NonVoter, cts.Token);
                    }
                    else
                    {
                        await follower.ServerStore.WaitForTopology(Leader.TopologyModification.Voter, cts.Token);
                    }
                }
            }

            await WaitForClusterTopologyOnAllNodes(clusterNodes);

            // ReSharper disable once PossibleNullReferenceException
            var condition = await leader.ServerStore.WaitForState(RachisState.Leader, CancellationToken.None).WaitAsync(numberOfNodes * _electionTimeoutInMs * 5);
            var states = "The leader has changed while waiting for cluster to become stable. All nodes status: ";
            if (condition == false)
            {
                InvalidOperationException e = null;
                if (actualLeaderIndex == null)
                {
                    // leader changed, try get the new leader if no leader index was selected
                    try
                    {
                        leader = await ActionWithLeader(_ => Task.CompletedTask, clusterNodes);
                        return (clusterNodes, leader, certificates);
                    }
                    catch (InvalidOperationException ex)
                    {
                        e = ex;
                    }
                }
                states += GetLastStatesFromAllServersOrderedByTime();
                if (e != null)
                    states += $"{Environment.NewLine}{e}";
            }
            Assert.True(condition, states);
            return (clusterNodes, leader, certificates);
        }
        public TestCertificatesHolder GenerateAndSaveSelfSignedCertificate(bool createNew = false, [CallerMemberName] string caller = null)
        {
            if (createNew)
            {
                return(ReturnCertificatesHolder(Generate(caller, Interlocked.Increment(ref Counter))));
            }

            var selfSignedCertificates = SelfSignedCertificates;

            if (selfSignedCertificates != null)
            {
                return(ReturnCertificatesHolder(selfSignedCertificates));
            }

            lock (typeof(TestBase))
            {
                selfSignedCertificates = SelfSignedCertificates;
                if (selfSignedCertificates == null)
                {
                    SelfSignedCertificates = selfSignedCertificates = Generate(caller);
                }

                return(ReturnCertificatesHolder(selfSignedCertificates));
            }

            TestCertificatesHolder ReturnCertificatesHolder(TestCertificatesHolder certificates)
            {
                return(new TestCertificatesHolder(certificates, _parent.GetTempFileName));
            }

            TestCertificatesHolder Generate(string caller, int gen = 0)
            {
                var log = new StringBuilder();

                byte[] certBytes;
                string serverCertificatePath = null;

                serverCertificatePath = Path.Combine(Path.GetTempPath(), $"Server-{gen}-{RavenVersionAttribute.Instance.Build}-{DateTime.Today:yyyy-MM-dd}.pfx");

                if (File.Exists(serverCertificatePath) == false)
                {
                    try
                    {
                        certBytes = CertificateUtils.CreateSelfSignedTestCertificate(Environment.MachineName, "RavenTestsServer", log);
                    }
                    catch (Exception e)
                    {
                        throw new CryptographicException($"Unable to generate the test certificate for the machine '{Environment.MachineName}'. Log: {log}", e);
                    }

                    if (certBytes.Length == 0)
                    {
                        throw new CryptographicException($"Test certificate length is 0 bytes. Machine: '{Environment.MachineName}', Log: {log}");
                    }

                    try
                    {
                        File.WriteAllBytes(serverCertificatePath, certBytes);
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException("Failed to write the test certificate to a temp file." +
                                                            $"tempFileName = {serverCertificatePath}" +
                                                            $"certBytes.Length = {certBytes.Length}" +
                                                            $"MachineName = {Environment.MachineName}.", e);
                    }
                }
                else
                {
                    certBytes = File.ReadAllBytes(serverCertificatePath);
                }
                X509Certificate2 serverCertificate;

                try
                {
                    serverCertificate = new X509Certificate2(certBytes, (string)null, X509KeyStorageFlags.MachineKeySet);
                }
                catch (Exception e)
                {
                    throw new CryptographicException($"Unable to load the test certificate for the machine '{Environment.MachineName}'. Log: {log}", e);
                }

                SecretProtection.ValidatePrivateKey(serverCertificatePath, null, certBytes, out var pk);
                SecretProtection.ValidateKeyUsages(serverCertificatePath, serverCertificate, validateKeyUsages: true);

                var clientCertificate1Path = GenerateClientCertificate(1, serverCertificate, pk);
                var clientCertificate2Path = GenerateClientCertificate(2, serverCertificate, pk);
                var clientCertificate3Path = GenerateClientCertificate(3, serverCertificate, pk);

                return(new TestCertificatesHolder(serverCertificatePath, clientCertificate1Path, clientCertificate2Path, clientCertificate3Path));
            }

            string GenerateClientCertificate(int index, X509Certificate2 serverCertificate, Org.BouncyCastle.Pkcs.AsymmetricKeyEntry pk)
            {
                string name = $"{Environment.MachineName}_CC_{RavenVersionAttribute.Instance.Build}_{index}_{DateTime.Today:yyyy-MM-dd}";
                string clientCertificatePath = Path.Combine(Path.GetTempPath(), name + ".pfx");

                if (File.Exists(clientCertificatePath) == false)
                {
                    CertificateUtils.CreateSelfSignedClientCertificate(
                        name,
                        new RavenServer.CertificateHolder
                    {
                        Certificate = serverCertificate,
                        PrivateKey  = pk
                    },
                        out var certBytes, DateTime.UtcNow.Date.AddYears(5));

                    try
                    {
                        File.WriteAllBytes(clientCertificatePath, certBytes);
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException("Failed to write the test certificate to a temp file." +
                                                            $"tempFileName = {clientCertificatePath}" +
                                                            $"certBytes.Length = {certBytes.Length}" +
                                                            $"MachineName = {Environment.MachineName}.", e);
                    }
                }

                return(clientCertificatePath);
            }
        }
        public TestCertificatesHolder SetupServerAuthentication(IDictionary <string, string> customSettings = null, string serverUrl = null, TestCertificatesHolder certificates = null, [CallerMemberName] string caller = null)
        {
            if (customSettings == null)
            {
                customSettings = new ConcurrentDictionary <string, string>();
            }

            if (certificates == null)
            {
                certificates = GenerateAndSaveSelfSignedCertificate(caller: caller);
            }

            if (customSettings.TryGetValue(RavenConfiguration.GetKey(x => x.Security.CertificateLoadExec), out var _) == false)
            {
                customSettings[RavenConfiguration.GetKey(x => x.Security.CertificatePath)] = certificates.ServerCertificatePath;
            }

            customSettings[RavenConfiguration.GetKey(x => x.Core.ServerUrls)] = serverUrl ?? "https://" + Environment.MachineName + ":0";

            _parent.DoNotReuseServer(customSettings);

            return(certificates);
        }
 public X509Certificate2 RegisterClientCertificate(TestCertificatesHolder certificates, Dictionary <string, DatabaseAccess> permissions, SecurityClearance clearance = SecurityClearance.ValidUser, RavenServer server = null)
 {
     return(RegisterClientCertificate(certificates.ServerCertificate.Value, certificates.ClientCertificate1.Value, permissions, clearance, server));
 }