public async void EncryptedWriteAndReadAsync(string keyIdBase64, KmsKeyLocation kmsKeyLocation)
        {
            // Construct a JSON Schema
            var schema = JsonSchemaCreator.CreateJsonSchema(keyIdBase64);

            // Construct an auto-encrypting client
            var autoEncryptingClient = CreateAutoEncryptingClient(
                kmsKeyLocation,
                _keyVaultNamespace,
                schema);

            // Set our working database and collection to medicalRecords.patients
            var collection = autoEncryptingClient
                             .GetDatabase(_medicalRecordsNamespace.DatabaseNamespace.DatabaseName)
                             .GetCollection <BsonDocument>(_medicalRecordsNamespace.CollectionName);

            var ssnQuery = Builders <BsonDocument> .Filter.Eq("ssn", __sampleSsnValue);

            // Upsert (update document if found, otherwise create it) a document into the collection
            var medicalRecordUpdateResult = await collection
                                            .UpdateOneAsync(ssnQuery, new BsonDocument("$set", __sampleDocFields), new UpdateOptions()
            {
                IsUpsert = true
            });

            if (!medicalRecordUpdateResult.UpsertedId.IsBsonNull)
            {
                Console.WriteLine("Successfully upserted the sample document!");
            }

            // Query by SSN field with auto-encrypting client
            var result = collection.Find(ssnQuery).Single();

            Console.WriteLine($"Encrypted client query by the SSN (deterministically-encrypted) field:\n {result}\n");
        }
        private IMongoClient CreateAutoEncryptingClient(
            KmsKeyLocation kmsKeyLocation,
            CollectionNamespace keyVaultNamespace,
            BsonDocument schema)
        {
            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();

            // Specify the local master encryption key
            if (kmsKeyLocation == KmsKeyLocation.Local)
            {
                var localMasterKeyBase64 = File.ReadAllText(__localMasterKeyPath);
                var localMasterKeyBytes  = Convert.FromBase64String(localMasterKeyBase64);
                var localOptions         = new Dictionary <string, object>
                {
                    { "key", localMasterKeyBytes }
                };
                kmsProviders.Add("local", localOptions);
            }

            //
            var schemaMap = new Dictionary <string, BsonDocument>();

            schemaMap.Add(_medicalRecordsNamespace.ToString(), schema);

            // Specify location of mongocryptd binary, if necessary
            var extraOptions = new Dictionary <string, object>()
            {
                // uncomment the following line if you are running mongocryptd manually
                // { "mongocryptdBypassSpawn", true }
            };

            // Create CSFLE-enabled MongoClient
            // The addition of the automatic encryption settings are what
            // change this from a standard MongoClient to a CSFLE-enabled one
            var clientSettings        = MongoClientSettings.FromConnectionString(_connectionString);
            var autoEncryptionOptions = new AutoEncryptionOptions(
                keyVaultNamespace: keyVaultNamespace,
                kmsProviders: kmsProviders,
                schemaMap: schemaMap,
                extraOptions: extraOptions);

            clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
            return(new MongoClient(clientSettings));
        }
        private IMongoClient CreateAutoEncryptingClient(
            KmsKeyLocation kmsKeyLocation,
            CollectionNamespace keyVaultNamespace,
            BsonDocument schema)
        {
            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();

            switch (kmsKeyLocation)
            {
            case KmsKeyLocation.Local:
                var localMasterKeyBase64 = File.ReadAllText(__localMasterKeyPath);
                var localMasterKeyBytes  = Convert.FromBase64String(localMasterKeyBase64);
                var localOptions         = new Dictionary <string, object>
                {
                    { "key", localMasterKeyBytes }
                };
                kmsProviders.Add("local", localOptions);
                break;

            case KmsKeyLocation.AWS:
                var awsAccessKey       = Environment.GetEnvironmentVariable("FLE_AWS_ACCESS_KEY");
                var awsSecretAccessKey = Environment.GetEnvironmentVariable("FLE_AWS_SECRET_ACCESS_KEY");
                var awsKmsOptions      = new Dictionary <string, object>
                {
                    { "accessKeyId", awsAccessKey },
                    { "secretAccessKey", awsSecretAccessKey }
                };
                kmsProviders.Add("aws", awsKmsOptions);
                break;

            case KmsKeyLocation.Azure:
                var azureTenantId                 = Environment.GetEnvironmentVariable("FLE_AZURE_TENANT_ID");
                var azureClientId                 = Environment.GetEnvironmentVariable("FLE_AZURE_CLIENT_ID");
                var azureClientSecret             = Environment.GetEnvironmentVariable("FLE_AZURE_CLIENT_SECRET");
                var azureIdentityPlatformEndpoint = Environment.GetEnvironmentVariable("FLE_AZURE_IDENTIFY_PLATFORM_ENPDOINT");     // Optional, only needed if user is using a non-commercial Azure instance

                var azureKmsOptions = new Dictionary <string, object>
                {
                    { "tenantId", azureTenantId },
                    { "clientId", azureClientId },
                    { "clientSecret", azureClientSecret },
                };
                if (azureIdentityPlatformEndpoint != null)
                {
                    azureKmsOptions.Add("identityPlatformEndpoint", azureIdentityPlatformEndpoint);
                }
                kmsProviders.Add("azure", azureKmsOptions);
                break;

            case KmsKeyLocation.GCP:
                var gcpPrivateKey = Environment.GetEnvironmentVariable("FLE_GCP_PRIVATE_KEY");
                var gcpEmail      = Environment.GetEnvironmentVariable("FLE_GCP_EMAIL");
                var gcpKmsOptions = new Dictionary <string, object>
                {
                    { "privateKey", gcpPrivateKey },
                    { "email", gcpEmail },
                };
                kmsProviders.Add("gcp", gcpKmsOptions);
                break;
            }

            var schemaMap = new Dictionary <string, BsonDocument>();

            schemaMap.Add(_medicalRecordsNamespace.ToString(), schema);

            var extraOptions = new Dictionary <string, object>()
            {
                // uncomment the following line if you are running mongocryptd manually
                // { "mongocryptdBypassSpawn", true }
            };

            var clientSettings        = MongoClientSettings.FromConnectionString(_connectionString);
            var autoEncryptionOptions = new AutoEncryptionOptions(
                keyVaultNamespace: keyVaultNamespace,
                kmsProviders: kmsProviders,
                schemaMap: schemaMap,
                extraOptions: extraOptions);

            clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
            return(new MongoClient(clientSettings));
        }