public string CreateKeyWithGcpKmsProvider()
        {
            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();

            var gcpPrivateKey = Environment.GetEnvironmentVariable("FLE_GCP_PRIVATE_KEY");
            var gcpEmail      = Environment.GetEnvironmentVariable("FLE_GCP_EMAIL");
            var gcpEndpoint   = Environment.GetEnvironmentVariable("FLE_GCP_IDENTITY_ENDPOINT"); // Optional, defaults to "oauth2.googleapis.com".
            var gcpKmsOptions = new Dictionary <string, object>
            {
                { "privateKey", gcpPrivateKey },
                { "email", gcpEmail },
            };

            if (gcpEndpoint != null)
            {
                gcpKmsOptions.Add("endpoint", gcpEndpoint);
            }
            kmsProviders.Add("gcp", gcpKmsOptions);

            var clientEncryption     = GetClientEncryption(kmsProviders);
            var gcpDataKeyProjectId  = Environment.GetEnvironmentVariable("FLE_GCP_PROJ_ID");
            var gcpDataKeyLocation   = Environment.GetEnvironmentVariable("FLE_GCP_KEY_LOC"); // Optional. e.g. "global"
            var gcpDataKeyKeyRing    = Environment.GetEnvironmentVariable("FLE_GCP_KEY_RING");
            var gcpDataKeyKeyName    = Environment.GetEnvironmentVariable("FLE_GCP_KEY_NAME");
            var gcpDataKeyKeyVersion = Environment.GetEnvironmentVariable("FLE_GCP_KEY_VERSION");  // Optional
            var gcpDataKeyEndpoint   = Environment.GetEnvironmentVariable("FLE_GCP_KMS_ENDPOINT"); // Optional, KMS URL, defaults to https://www.googleapis.com/auth/cloudkms

            var dataKeyOptions = new DataKeyOptions(
                masterKey: new BsonDocument
            {
                { "projectId", gcpDataKeyProjectId },
                { "location", gcpDataKeyLocation },
                { "keyRing", gcpDataKeyKeyRing },
                { "keyName", gcpDataKeyKeyName },
                { "keyVersion", () => gcpDataKeyKeyVersion, gcpDataKeyKeyVersion != null },
                { "endpoint", () => gcpDataKeyEndpoint, gcpDataKeyEndpoint != null }
            });

            var dataKeyId = clientEncryption.CreateDataKey("gcp", dataKeyOptions, CancellationToken.None);

            Console.WriteLine($"DataKeyId [UUID]: {dataKeyId}");
            var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));

            Console.WriteLine($"DataKeyId [base64]: {dataKeyIdBase64}");

            ValidateKey(dataKeyId);
            return(dataKeyIdBase64);
        }
 private Guid CreateDataKey(
     ClientEncryption clientEncryption,
     string kmsProvider,
     DataKeyOptions dataKeyOptions,
     bool async)
 {
     if (async)
     {
         return(clientEncryption
                .CreateDataKeyAsync(kmsProvider, dataKeyOptions, CancellationToken.None)
                .GetAwaiter()
                .GetResult());
     }
     else
     {
         return(clientEncryption.CreateDataKey(kmsProvider, dataKeyOptions, CancellationToken.None));
     }
 }
        public string CreateKeyWithAzureKmsProvider()
        {
            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();

            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);

            var clientEncryption      = GetClientEncryption(kmsProviders);
            var azureKeyName          = Environment.GetEnvironmentVariable("FLE_AZURE_KEY_NAME");
            var azureKeyVaultEndpoint = Environment.GetEnvironmentVariable("FLE_AZURE_KEYVAULT_ENDPOINT"); // typically <azureKeyName>.vault.azure.net
            var azureKeyVersion       = Environment.GetEnvironmentVariable("FLE_AZURE_KEY_VERSION");       // Optional
            var dataKeyOptions        = new DataKeyOptions(
                masterKey: new BsonDocument
            {
                { "keyName", azureKeyName },
                { "keyVaultEndpoint", azureKeyVaultEndpoint },
                { "keyVersion", () => azureKeyVersion, azureKeyVersion != null }
            });

            var dataKeyId = clientEncryption.CreateDataKey("azure", dataKeyOptions, CancellationToken.None);

            Console.WriteLine($"Azure DataKeyId [UUID]: {dataKeyId}");
            var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));

            Console.WriteLine($"Azure DataKeyId [base64]: {dataKeyIdBase64}");

            ValidateKey(dataKeyId);
            return(dataKeyIdBase64);
        }
        public string CreateKeyWithAwsKmsProvider()
        {
            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();

            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);

            var clientEncryption = GetClientEncryption(kmsProviders);

            var awsKeyARN      = Environment.GetEnvironmentVariable("FLE_AWS_KEY_ARN");  // e.g. "arn:aws:kms:us-east-2:111122223333:alias/test-key"
            var awsKeyRegion   = Environment.GetEnvironmentVariable("FLE_AWS_KEY_REGION");
            var awsEndpoint    = Environment.GetEnvironmentVariable("FLE_AWS_ENDPOINT"); // Optional, AWS KMS URL.
            var dataKeyOptions = new DataKeyOptions(
                masterKey: new BsonDocument
            {
                { "region", awsKeyRegion },
                { "key", awsKeyARN },
                { "endpoint", () => awsEndpoint, awsEndpoint != null }
            });

            var dataKeyId = clientEncryption.CreateDataKey("aws", dataKeyOptions, CancellationToken.None);

            Console.WriteLine($"AWS DataKeyId [UUID]: {dataKeyId}");
            var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));

            Console.WriteLine($"AWS DataKeyId [base64]: {dataKeyIdBase64}");

            ValidateKey(dataKeyId);
            return(dataKeyIdBase64);
        }
        // public void ClientSideEncryptionAutoEncryptionSettingsTour()
        public static void Main(string[] args)
        {
            var localMasterKey = Convert.FromBase64String(LocalMasterKey);

            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();
            var localKey     = new Dictionary <string, object>
            {
                { "key", localMasterKey }
            };

            kmsProviders.Add("local", localKey);

            var keyVaultDB        = "keyVault";
            var keystore          = "__keystore";
            var keyVaultNamespace = CollectionNamespace.FromFullName($"{keyVaultDB}.{keystore}");

            var keyVaultMongoClient      = new MongoClient();
            var clientEncryptionSettings = new ClientEncryptionOptions(
                keyVaultMongoClient,
                keyVaultNamespace,
                kmsProviders);
            var clientEncryption = new ClientEncryption(clientEncryptionSettings);

            keyVaultMongoClient.GetDatabase(keyVaultDB).DropCollection(keystore);

            var altKeyName      = new[] { "csharpDataKey01" };
            var dataKeyOptions  = new DataKeyOptions(alternateKeyNames: altKeyName);
            var dataKeyId       = clientEncryption.CreateDataKey("local", dataKeyOptions, CancellationToken.None);
            var base64DataKeyId = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));

            clientEncryption.Dispose();

            var collectionNamespace = CollectionNamespace.FromFullName("test.coll");

            var schemaMap = $@"{{
                properties: {{
                    SSN: {{
                        encrypt: {{
                            keyId: [{{
                                '$binary' : {{
                                    'base64' : '{base64DataKeyId}',
                                    'subType' : '04'
                                }}
                            }}],
                        bsonType: 'string',
                        algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
                        }}
                    }}
                }},
                'bsonType': 'object'
            }}";
            var autoEncryptionSettings = new AutoEncryptionOptions(
                keyVaultNamespace,
                kmsProviders,
                schemaMap: new Dictionary <string, BsonDocument>()
            {
                { collectionNamespace.ToString(), BsonDocument.Parse(schemaMap) }
            });
            var clientSettings = new MongoClientSettings
            {
                AutoEncryptionOptions = autoEncryptionSettings
            };
            var client   = new MongoClient(clientSettings);
            var database = client.GetDatabase("test");

            database.DropCollection("coll");

            var collection = database.GetCollection <BsonDocument>("coll");

            collection.InsertOne(new BsonDocument("SSN", "123456789"));

            var result = collection.Find(FilterDefinition <BsonDocument> .Empty).First();

            Console.WriteLine(result.ToJson());
        }
        public void CustomEndpointTest([Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            using (var client = ConfigureClient())
                using (var clientEncryption = ConfigureClientEncryption(client.Wrapped as MongoClient))
                {
                    var testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com:443" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com:12345" }
                    };
                    var exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.InnerException.Should().BeAssignableTo <SocketException>();

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-2.amazonaws.com" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.Message.Should().Contain("us-east-1");

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "example.com" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.Message.Should().Contain("parse error");

                    // additional not spec tests
                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "$test$" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.InnerException.Should().BeAssignableTo <SocketException>();

                    void TestCase(BsonDocument masterKey)
                    {
                        var dataKeyOptions = new DataKeyOptions(masterKey: masterKey);
                        var dataKey        = CreateDataKey(clientEncryption, "aws", dataKeyOptions, async);

                        var encryptOptions = new EncryptOptions(
                            algorithm: EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                            keyId: dataKey);
                        var value     = "test";
                        var encrypted = ExplicitEncrypt(clientEncryption, encryptOptions, value, async);
                        var decrypted = ExplicitDecrypt(clientEncryption, encrypted, async);

                        decrypted.Should().Be(BsonValue.Create(value));
                    }
                }
        }