コード例 #1
0
        public void Authentication_succeeds_with_MONGODB_X509_mechanism(
            [Values(false, true)] bool async)
        {
            RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH", isDefined: true);
            RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD", isDefined: true);
            RequireServer.Check().Tls(required: true);

            var pathToClientCertificate = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH");
            var password          = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD");
            var clientCertificate = new X509Certificate2(pathToClientCertificate, password);

            var userName = GetRfc2253FormattedUsernameFromX509ClientCertificate(clientCertificate);

            DropDatabaseUser(DriverTestConfiguration.Client, database: "$external", userName);
            CreateX509DatabaseUser(DriverTestConfiguration.Client, userName);

            var settings      = DriverTestConfiguration.GetClientSettings().Clone();
            var serverVersion = CoreTestConfiguration.ServerVersion;

            if (Feature.ServerExtractsUsernameFromX509Certificate.IsSupported(serverVersion))
            {
                settings.Credential = MongoCredential.CreateMongoX509Credential();
            }
            else
            {
                settings.Credential = MongoCredential.CreateMongoX509Credential(userName);
            }
            settings.SslSettings = settings.SslSettings.Clone();
            settings.SslSettings.ClientCertificates = new[] { clientCertificate };

            AssertAuthenticationSucceeds(settings, async, speculativeAuthenticatationShouldSucceedIfPossible: true);
        }
コード例 #2
0
        public void Should_call_custom_server_selector()
        {
            var eventCapturer = new EventCapturer()
                                .Capture <ClusterSelectingServerEvent>()
                                .Capture <ClusterSelectedServerEvent>();
            var customServerSelector = new CustomServerSelector();

            using (var client = DriverTestConfiguration.CreateDisposableClient(
                       clientSettings =>
                       clientSettings.ClusterConfigurator =
                           c =>
            {
                c.ConfigureCluster(s => s.With(postServerSelector: customServerSelector));
                c.Subscribe(eventCapturer);
            },
                       logger: null))
            {
                var collection = client
                                 .GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName)
                                 .GetCollection <BsonDocument>(DriverTestConfiguration.CollectionNamespace.CollectionName)
                                 .WithReadPreference(ReadPreference.Nearest);

                customServerSelector.CustomSelectorWasCalled = false;
                eventCapturer.Clear();

                collection.CountDocuments(new BsonDocument());

                customServerSelector.CustomSelectorWasCalled.Should().BeTrue();
                eventCapturer.Next().Should().BeOfType <ClusterSelectingServerEvent>();
                eventCapturer.Next().Should().BeOfType <ClusterSelectedServerEvent>();
            }
        }
コード例 #3
0
 private void AssertAuthenticationSucceeds(
     MongoClientSettings settings,
     bool async,
     bool speculativeAuthenticatationShouldSucceedIfPossible = true)
 {
     // If we don't use a DisposableClient, the second run of AuthenticationSucceedsWithMongoDB_X509_mechanism
     // will fail because the backing Cluster's connections will be associated with a dropped user
     using (var client = DriverTestConfiguration.CreateDisposableclient(settings))
     {
         // The first command executed with the MongoClient triggers either the sync or async variation of the
         // MongoClient's IAuthenticator
         if (async)
         {
             _ = client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList();
         }
         else
         {
             _ = client.ListDatabaseNames().ToList();
         }
         if (Feature.SpeculativeAuthentication.IsSupported(CoreTestConfiguration.ServerVersion) &&
             speculativeAuthenticatationShouldSucceedIfPossible)
         {
             var cancellationToken = CancellationToken.None;
             var serverSelector    = new ReadPreferenceServerSelector(settings.ReadPreference);
             var server            = client.Cluster.SelectServer(serverSelector, cancellationToken);
             var channel           = server.GetChannel(cancellationToken);
             var isMasterResult    = channel.ConnectionDescription.IsMasterResult;
             isMasterResult.SpeculativeAuthenticate.Should().NotBeNull();
         }
     }
 }
コード例 #4
0
        public void KillCursor_should_actually_work()
        {
            RequireServer.Check().Supports(Feature.KillCursorsCommand);
            var eventCapturer = new EventCapturer().Capture <CommandSucceededEvent>(x => x.CommandName.Equals("killCursors"));

            using (var client = DriverTestConfiguration.CreateDisposableClient(eventCapturer))
            {
                IAsyncCursor <BsonDocument> cursor;
                var database   = client.GetDatabase("test");
                var collection = database.GetCollection <BsonDocument>(GetType().Name);
                var documents  = new List <BsonDocument>();
                for (int i = 0; i < 1000; i++)
                {
                    documents.Add(new BsonDocument("x", i));
                }

                collection.InsertMany(documents);
                cursor = collection.FindSync("{}");
                cursor.MoveNext();

                var cursorId = ((AsyncCursor <BsonDocument>)cursor)._cursorId();
                cursorId.Should().NotBe(0);
                cursor.Dispose();

                var desiredResult = BsonDocument.Parse($"{{ \"cursorsKilled\" : [{cursorId}], \"cursorsNotFound\" : [], " +
                                                       $"\"cursorsAlive\" : [], \"cursorsUnknown\" : [], \"ok\" : 1.0 }}");
                var result = ((CommandSucceededEvent)eventCapturer.Events[0]).Reply;
                result.IsSameOrEqualTo(desiredResult);
            }
        }
コード例 #5
0
 private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, bool useMultipleShardRouters)
 {
     return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) =>
     {
         settings.ClusterConfigurator = c => c.Subscribe(eventCapturer);
     },
                                                           useMultipleShardRouters));
 }
コード例 #6
0
 // private methods
 private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, ReadPreference readPreference)
 {
     return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) =>
     {
         settings.ClusterConfigurator = c => c.Subscribe(eventCapturer);
         settings.ReadPreference = readPreference;
     }));
 }
コード例 #7
0
 private DisposableMongoClient GetClient(Action <ClusterBuilder> clusterConfigurator)
 {
     return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings clientSettings) =>
     {
         clientSettings.ClusterConfigurator = clusterConfigurator;
         clientSettings.RetryWrites = true;
     }));
 }
コード例 #8
0
 private DisposableMongoClient CreateDisposableClient(EventCapturer capturedEvents)
 {
     return(DriverTestConfiguration.CreateDisposableClient(
                settings =>
     {
         settings.RetryWrites = false;
         settings.ClusterConfigurator = c => { c.Subscribe(capturedEvents); };
     }));
 }
コード例 #9
0
 private DisposableMongoClient GetClient(Action <ClusterBuilder> clusterConfigurator, bool retryWrites = true)
 {
     return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings clientSettings) =>
     {
         clientSettings.ClusterConfigurator = clusterConfigurator;
         clientSettings.RetryWrites = retryWrites;
     },
                                                           logger: CreateLogger <DisposableMongoClient>()));
 }
コード例 #10
0
        public void ListDatabases_should_invoke_the_correct_operation(
            [Values(false, true)] bool usingSession,
            [Values(false, true)] bool async)
        {
            var operationExecutor = new MockOperationExecutor();
            var subject           = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings());
            var session           = CreateClientSession();
            var cancellationToken = new CancellationTokenSource().Token;
            var filterDocument    = BsonDocument.Parse("{ name : \"awesome\" }");
            var filterDefinition  = (FilterDefinition <BsonDocument>)filterDocument;
            var nameOnly          = true;
            var options           = new ListDatabasesOptions
            {
                Filter   = filterDefinition,
                NameOnly = nameOnly
            };

            if (usingSession)
            {
                if (async)
                {
                    subject.ListDatabasesAsync(session, options, cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.ListDatabases(session, options, cancellationToken);
                }
            }
            else
            {
                if (async)
                {
                    subject.ListDatabasesAsync(options, cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.ListDatabases(options, cancellationToken);
                }
            }

            var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >();

            if (usingSession)
            {
                call.SessionId.Should().BeSameAs(session.ServerSession.Id);
            }
            else
            {
                call.UsedImplicitSession.Should().BeTrue();
            }
            call.CancellationToken.Should().Be(cancellationToken);

            var operation = call.Operation.Should().BeOfType <ListDatabasesOperation>().Subject;

            operation.Filter.Should().Be(filterDocument);
            operation.NameOnly.Should().Be(nameOnly);
        }
 private DisposableMongoClient CreateDisposableClient(EventCapturer capturedEvents)
 {
     return(DriverTestConfiguration.CreateDisposableClient(
                settings =>
     {
         settings.HeartbeatInterval = TimeSpan.FromMilliseconds(5);     // the default value for spec tests
         settings.RetryWrites = false;
         settings.ClusterConfigurator = c => { c.Subscribe(capturedEvents); };
     }));
 }
コード例 #12
0
        public void DropDatabase_should_invoke_the_correct_operation(
            [Values(false, true)] bool usingSession,
            [Values(false, true)] bool async)
        {
            var operationExecutor = new MockOperationExecutor();
            var writeConcern      = new WriteConcern(1);
            var subject           = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings()).WithWriteConcern(writeConcern);
            var session           = CreateClientSession();
            var cancellationToken = new CancellationTokenSource().Token;

            if (usingSession)
            {
                if (async)
                {
                    subject.DropDatabaseAsync(session, "awesome", cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.DropDatabase(session, "awesome", cancellationToken);
                }
            }
            else
            {
                if (async)
                {
                    subject.DropDatabaseAsync("awesome", cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.DropDatabase("awesome", cancellationToken);
                }
            }

            var call = operationExecutor.GetWriteCall <BsonDocument>();

            if (usingSession)
            {
                call.SessionId.Should().BeSameAs(session.ServerSession.Id);
            }
            else
            {
                call.UsedImplicitSession.Should().BeTrue();
            }
            call.CancellationToken.Should().Be(cancellationToken);

            var dropDatabaseOperation = call.Operation.Should().BeOfType <DropDatabaseOperation>().Subject;

            dropDatabaseOperation.DatabaseNamespace.Should().Be(new DatabaseNamespace("awesome"));
            dropDatabaseOperation.WriteConcern.Should().BeSameAs(writeConcern);
        }
コード例 #13
0
        private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, bool useMultipleShardRouters)
        {
            // Increase localThresholdMS and wait until all nodes are discovered to avoid false positives.
            var client = DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) =>
            {
                settings.ClusterConfigurator = c => c.Subscribe(eventCapturer);
                settings.LocalThreshold      = TimeSpan.FromMilliseconds(1000);
            },
                                                                        useMultipleShardRouters);
            var timeOut = TimeSpan.FromSeconds(60);

            SpinWait.SpinUntil(() => client.Cluster.Description.Type != ClusterType.Unknown, timeOut).Should().BeTrue();
            return(client);
        }
コード例 #14
0
        public static MongoServer GetServer(
            bool?retryWrites = null)
        {
            var settings = DriverTestConfiguration.GetClientSettings();

            if (retryWrites.HasValue)
            {
                settings.RetryWrites = retryWrites.Value;
            }
            var client = new MongoClient(settings);

#pragma warning disable 618
            return(client.GetServer());

#pragma warning restore 618
        }
コード例 #15
0
        private void AssertAuthenticationFails(MongoClientSettings settings, bool async)
        {
            using (var client = DriverTestConfiguration.CreateDisposableclient(settings))
            {
                Exception exception;
                if (async)
                {
                    exception = Record.Exception(() => client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList());
                }
                else
                {
                    exception = Record.Exception(() => client.ListDatabaseNames().ToList());
                }

                exception.Should().BeOfType <MongoAuthenticationException>();
            }
        }
コード例 #16
0
        public void ListDatabases_should_invoke_the_correct_operation(
            [Values(false, true)] bool usingSession,
            [Values(false, true)] bool async)
        {
            var operationExecutor = new MockOperationExecutor();
            var subject           = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings());
            var session           = CreateClientSession();
            var cancellationToken = new CancellationTokenSource().Token;

            if (usingSession)
            {
                if (async)
                {
                    subject.ListDatabasesAsync(session, cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.ListDatabases(session, cancellationToken);
                }
            }
            else
            {
                if (async)
                {
                    subject.ListDatabasesAsync(cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.ListDatabases(cancellationToken);
                }
            }

            var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >();

            if (usingSession)
            {
                call.SessionId.Should().BeSameAs(session.ServerSession.Id);
            }
            else
            {
                call.UsedImplicitSession.Should().BeTrue();
            }
            call.CancellationToken.Should().Be(cancellationToken);

            call.Operation.Should().BeOfType <ListDatabasesOperation>();
        }
コード例 #17
0
        // private methods

        /* We can't use DriverTestConfiguration.CreateDisposableClient because that results in a call to check
         * the cluster type, which fails because a connection cannot be established to the mongod when testing
         * the revoked certificate case */
        private DisposableMongoClient CreateDisposableMongoClient(bool tlsInsecure)
        {
            var settings = DriverTestConfiguration.GetClientSettings().Clone();

            settings.SslSettings = new SslSettings {
                CheckCertificateRevocation = true
            };
            // setting AllowInsecureTls= true will automatically set CheckCertificateRevocation to false
            settings.AllowInsecureTls = tlsInsecure;

            /* We want the heartbeat to fire so that we can get the HeartBeat exception in the cluster description
             * in the exception that will be thrown when testing invalid certificates */
            settings.HeartbeatInterval = TimeSpan.FromMilliseconds(500);

            /* We lower the server selection timeout to speed up tests, but choosing a value <=5s may
             * result in the driver being unable to perform OCSP endpoint checking in time, causing a
             * ServerSelectionTimeout that does include a certificate revocation status error message. */
            settings.ServerSelectionTimeout = TimeSpan.FromSeconds(5 * 2); // must be > 5s
            // settings.SdamLogFilename = @"C:\temp\sdam" + $"{tlsInsecure}.log";

            return(new DisposableMongoClient(new MongoClient(settings)));
        }
        public void Connection_pool_should_not_be_cleared_when_replSetStepDown_and_GetMore([Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.KeepConnectionPoolWhenReplSetStepDown).ClusterType(ClusterType.ReplicaSet);

            var eventCapturer = new EventCapturer().Capture <ConnectionPoolClearedEvent>();

            using (var client = CreateDisposableClient(eventCapturer))
            {
                var database = client.GetDatabase(_databaseName, new MongoDatabaseSettings {
                    WriteConcern = WriteConcern.WMajority
                });
                database.DropCollection(_databaseName);
                var collection = database.GetCollection <BsonDocument>(_collectionName, new MongoCollectionSettings {
                    WriteConcern = WriteConcern.WMajority
                });
                var adminDatabase = client.GetDatabase("admin").WithWriteConcern(WriteConcern.W1);

                collection.InsertMany(
                    new[]
                {
                    new BsonDocument("x", 1),
                    new BsonDocument("x", 2),
                    new BsonDocument("x", 3),
                    new BsonDocument("x", 4),
                    new BsonDocument("x", 5),
                });
                eventCapturer.Clear();

                var cursor = collection.FindSync(FilterDefinition <BsonDocument> .Empty, new FindOptions <BsonDocument> {
                    BatchSize = 2
                });
                cursor.MoveNext();

                foreach (var secondary in client.Cluster.Description.Servers.Where(c => c.Type == ServerType.ReplicaSetSecondary))
                {
                    RunOnSecondary(client, secondary.EndPoint, BsonDocument.Parse("{ replSetFreeze : 0 }"));
                }

                var          replSetStepDownCommand = BsonDocument.Parse("{ replSetStepDown : 30, force : true }");
                BsonDocument replSetStepDownResult;
                if (async)
                {
                    replSetStepDownResult = adminDatabase.RunCommandAsync <BsonDocument>(replSetStepDownCommand).GetAwaiter().GetResult();
                }
                else
                {
                    replSetStepDownResult = adminDatabase.RunCommand <BsonDocument>(replSetStepDownCommand);
                }

                replSetStepDownResult.Should().NotBeNull();
                replSetStepDownResult.GetValue("ok", false).ToBoolean().Should().BeTrue();

                cursor.MoveNext();

                eventCapturer.Events.Should().BeEmpty(); // it also means that no new PoolClearedEvent
            }

            void RunOnSecondary(IMongoClient primaryClient, EndPoint secondaryEndpoint, BsonDocument command)
            {
                var secondarySettings = primaryClient.Settings.Clone();

                secondarySettings.ClusterConfigurator = null;
#pragma warning disable CS0618 // Type or member is obsolete
                secondarySettings.ConnectionMode = ConnectionMode.Direct;
#pragma warning restore CS0618 // Type or member is obsolete
                var secondaryDnsEndpoint = (DnsEndPoint)secondaryEndpoint;
                secondarySettings.Server = new MongoServerAddress(secondaryDnsEndpoint.Host, secondaryDnsEndpoint.Port);
                using (var secondaryClient = DriverTestConfiguration.CreateDisposableClient(secondarySettings))
                {
                    var adminDatabase = secondaryClient.GetDatabase(DatabaseNamespace.Admin.DatabaseName);
                    adminDatabase.RunCommand <BsonDocument>(command);
                }
            }
        }
コード例 #19
0
        public void ListDatabaseNames_should_invoke_the_correct_operation(
            [Values(false, true)] bool usingSession,
            [Values(false, true)] bool async)
        {
            var operationExecutor       = new MockOperationExecutor();
            var subject                 = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings());
            var session                 = CreateClientSession();
            var cancellationToken       = new CancellationTokenSource().Token;
            var listDatabaseNamesResult = @"
            {
                ""databases"" : [
                    {
                        ""name"" : ""admin"",
                        ""sizeOnDisk"" : 131072,
                        ""empty"" : false
                    },
                    {
                        ""name"" : ""blog"",
                        ""sizeOnDisk"" : 11669504,
                        ""empty"" : false
                    },
                    {
                        ""name"" : ""test-chambers"",
                        ""sizeOnDisk"" : 222883840,
                        ""empty"" : false
                    },
                    {
                        ""name"" : ""recipes"",
                        ""sizeOnDisk"" : 73728,
                        ""empty"" : false
                    },
                    {
                        ""name"" : ""employees"",
                        ""sizeOnDisk"" : 225280,
                        ""empty"" : false
                    }
                ],
                ""totalSize"" : 252534784,
                ""ok"" : 1
            }";
            var operationResult         = BsonDocument.Parse(listDatabaseNamesResult);

            operationExecutor.EnqueueResult(CreateListDatabasesOperationCursor(operationResult));

            IList <string> databaseNames;

            if (async)
            {
                if (usingSession)
                {
                    databaseNames = subject.ListDatabaseNamesAsync(session, cancellationToken).GetAwaiter().GetResult().ToList();
                }
                else
                {
                    databaseNames = subject.ListDatabaseNamesAsync(cancellationToken).GetAwaiter().GetResult().ToList();
                }
            }
            else
            {
                if (usingSession)
                {
                    databaseNames = subject.ListDatabaseNames(session, cancellationToken).ToList();
                }
                else
                {
                    databaseNames = subject.ListDatabaseNames(cancellationToken).ToList();
                }
            }

            var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >();

            if (usingSession)
            {
                call.SessionId.Should().BeSameAs(session.ServerSession.Id);
            }
            else
            {
                call.UsedImplicitSession.Should().BeTrue();
            }

            call.CancellationToken.Should().Be(cancellationToken);

            var operation = call.Operation.Should().BeOfType <ListDatabasesOperation>().Subject;

            operation.NameOnly.Should().Be(true);
            databaseNames.Should().Equal(operationResult["databases"].AsBsonArray.Select(record => record["name"].AsString));
        }
コード例 #20
0
        public void Watch_should_invoke_the_correct_operation(
            [Values(false, true)] bool usingSession,
            [Values(false, true)] bool async)
        {
            var operationExecutor = new MockOperationExecutor();
            var clientSettings    = DriverTestConfiguration.GetClientSettings();
            var subject           = new MongoClient(operationExecutor, clientSettings);
            var session           = usingSession ? CreateClientSession() : null;
            var pipeline          = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >().Limit(1);
            var options           = new ChangeStreamOptions
            {
                BatchSize            = 123,
                Collation            = new Collation("en-us"),
                FullDocument         = ChangeStreamFullDocumentOption.UpdateLookup,
                MaxAwaitTime         = TimeSpan.FromSeconds(123),
                ResumeAfter          = new BsonDocument(),
                StartAtOperationTime = new BsonTimestamp(1, 2)
            };
            var cancellationToken = new CancellationTokenSource().Token;
            var renderedPipeline  = new[] { BsonDocument.Parse("{ $limit : 1 }") };

            if (usingSession)
            {
                if (async)
                {
                    subject.WatchAsync(session, pipeline, options, cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.Watch(session, pipeline, options, cancellationToken);
                }
            }
            else
            {
                if (async)
                {
                    subject.WatchAsync(pipeline, options, cancellationToken).GetAwaiter().GetResult();
                }
                else
                {
                    subject.Watch(pipeline, options, cancellationToken);
                }
            }

            var call = operationExecutor.GetReadCall <IAsyncCursor <ChangeStreamDocument <BsonDocument> > >();

            if (usingSession)
            {
                call.SessionId.Should().BeSameAs(session.ServerSession.Id);
            }
            else
            {
                call.UsedImplicitSession.Should().BeTrue();
            }
            call.CancellationToken.Should().Be(cancellationToken);

            var changeStreamOperation = call.Operation.Should().BeOfType <ChangeStreamOperation <ChangeStreamDocument <BsonDocument> > >().Subject;

            changeStreamOperation.BatchSize.Should().Be(options.BatchSize);
            changeStreamOperation.Collation.Should().BeSameAs(options.Collation);
            changeStreamOperation.CollectionNamespace.Should().BeNull();
            changeStreamOperation.DatabaseNamespace.Should().BeNull();
            changeStreamOperation.FullDocument.Should().Be(options.FullDocument);
            changeStreamOperation.MaxAwaitTime.Should().Be(options.MaxAwaitTime);
            changeStreamOperation.MessageEncoderSettings.Should().NotBeNull();
            changeStreamOperation.Pipeline.Should().Equal(renderedPipeline);
            changeStreamOperation.ReadConcern.Should().Be(clientSettings.ReadConcern);
            changeStreamOperation.ResultSerializer.Should().BeOfType <ChangeStreamDocumentSerializer <BsonDocument> >();
            changeStreamOperation.ResumeAfter.Should().Be(options.ResumeAfter);
            changeStreamOperation.StartAtOperationTime.Should().Be(options.StartAtOperationTime);
        }
コード例 #21
0
 private DisposableMongoClient GetClient(EventCapturer capturer)
 {
     return(DriverTestConfiguration.CreateDisposableClient(capturer));
 }