public async Task EncryptionResourceTokenAuthRestricted()
        {
            TestDoc testDoc = await EncryptionTests.CreateItemAsync(EncryptionTests.itemContainerCore, EncryptionTests.dekId, TestDoc.PathsToEncrypt);

            User restrictedUser = EncryptionTests.databaseCore.GetUser(Guid.NewGuid().ToString());
            await EncryptionTests.databaseCore.CreateUserAsync(restrictedUser.Id);

            PermissionProperties restrictedUserPermission = await restrictedUser.CreatePermissionAsync(
                new PermissionProperties(Guid.NewGuid().ToString(), PermissionMode.All, EncryptionTests.itemContainer));

            CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider());
            TestEncryptor encryptor = new TestEncryptor(dekProvider);

            (string endpoint, string _) = TestCommon.GetAccountInfo();
            CosmosClient clientForRestrictedUser = new CosmosClientBuilder(endpoint, restrictedUserPermission.Token)
                                                   .WithEncryptor(encryptor)
                                                   .Build();

            Database  databaseForRestrictedUser  = clientForRestrictedUser.GetDatabase(EncryptionTests.databaseCore.Id);
            Container containerForRestrictedUser = databaseForRestrictedUser.GetContainer(EncryptionTests.itemContainer.Id);

            await EncryptionTests.PerformForbiddenOperationAsync(() =>
                                                                 dekProvider.InitializeAsync(databaseForRestrictedUser, EncryptionTests.keyContainer.Id), "CosmosDekProvider.InitializeAsync");

            await EncryptionTests.PerformOperationOnUninitializedDekProviderAsync(() =>
                                                                                  dekProvider.DataEncryptionKeyContainer.ReadDataEncryptionKeyAsync(EncryptionTests.dekId), "DEK.ReadAsync");

            await EncryptionTests.PerformOperationOnUninitializedDekProviderAsync(() =>
                                                                                  containerForRestrictedUser.ReadItemAsync <TestDoc>(testDoc.Id, new PartitionKey(testDoc.PK)), "ReadItemAsync");

            await EncryptionTests.PerformOperationOnUninitializedDekProviderAsync(() =>
                                                                                  containerForRestrictedUser.ReadItemStreamAsync(testDoc.Id, new PartitionKey(testDoc.PK)), "ReadItemStreamAsync");
        }
        public static async Task ClassInitialize(TestContext context)
        {
            EncryptionTests.dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider());
            EncryptionTests.encryptor   = new TestEncryptor(EncryptionTests.dekProvider);

            EncryptionTests.client       = EncryptionTests.GetClient();
            EncryptionTests.databaseCore = (DatabaseInlineCore)await EncryptionTests.client.CreateDatabaseAsync(Guid.NewGuid().ToString());

            EncryptionTests.keyContainer = await EncryptionTests.databaseCore.CreateContainerAsync(Guid.NewGuid().ToString(), "/id", 400);

            await EncryptionTests.dekProvider.InitializeAsync(EncryptionTests.databaseCore, EncryptionTests.keyContainer.Id);


            EncryptionTests.itemContainer = await EncryptionTests.databaseCore.CreateContainerAsync(Guid.NewGuid().ToString(), "/PK", 400);

            EncryptionTests.itemContainerCore = (ContainerInlineCore)EncryptionTests.itemContainer;

            EncryptionTests.dekProperties = await EncryptionTests.CreateDekAsync(EncryptionTests.dekProvider, EncryptionTests.dekId);
        }
Пример #3
0
        public async Task ClassInitialize(TestContext context)
        {
            EncryptionContainerTests.dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider());
            EncryptionContainerTests.encryptor   = new TestEncryptor(EncryptionContainerTests.dekProvider);

            EncryptionContainerTests.client   = TestCommon.CreateCosmosClient();
            EncryptionContainerTests.database = await EncryptionContainerTests.client.CreateDatabaseAsync(Guid.NewGuid().ToString());

            EncryptionContainerTests.keyContainer = await EncryptionContainerTests.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id", 400);

            await EncryptionContainerTests.dekProvider.InitializeAsync(EncryptionContainerTests.database, EncryptionContainerTests.keyContainer.Id);

            EncryptionContainerTests.itemContainer = await EncryptionContainerTests.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/PK", 400);

            EncryptionContainerTests.propertyEncryptionContainer = EncryptionContainerTests.itemContainer.WithPropertyEncryptor(encryptor, EncryptionContainerTests.PathsToEncrypt);
            EncryptionContainerTests.pdekProperties = await EncryptionContainerTests.CreatePropertyDekAsync(EncryptionContainerTests.dekProvider, EncryptionContainerTests.pdekId);

            EncryptionContainerTests.twoPropertyEncryptionContainer       = EncryptionContainerTests.itemContainer.WithPropertyEncryptor(encryptor, EncryptionContainerTests.PathsToEncrypt3);
            EncryptionContainerTests.twoPropertyOneDekEncryptionContainer = EncryptionContainerTests.itemContainer.WithPropertyEncryptor(encryptor, EncryptionContainerTests.PathsToEncrypt4);
        }
        public async Task EncryptionResourceTokenAuthAllowed()
        {
            User keyManagerUser = EncryptionTests.databaseCore.GetUser(Guid.NewGuid().ToString());
            await EncryptionTests.databaseCore.CreateUserAsync(keyManagerUser.Id);

            PermissionProperties keyManagerUserPermission = await keyManagerUser.CreatePermissionAsync(
                new PermissionProperties(Guid.NewGuid().ToString(), PermissionMode.All, EncryptionTests.keyContainer));

            CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider());
            TestEncryptor encryptor = new TestEncryptor(dekProvider);

            (string endpoint, string _) = TestCommon.GetAccountInfo();
            CosmosClient clientForKeyManagerUser = new CosmosClientBuilder(endpoint, keyManagerUserPermission.Token)
                                                   .WithEncryptor(encryptor)
                                                   .Build();

            Database databaseForKeyManagerUser = clientForKeyManagerUser.GetDatabase(EncryptionTests.databaseCore.Id);

            await dekProvider.InitializeAsync(databaseForKeyManagerUser, EncryptionTests.keyContainer.Id);

            DataEncryptionKeyProperties readDekProperties = await dekProvider.DataEncryptionKeyContainer.ReadDataEncryptionKeyAsync(EncryptionTests.dekId);

            Assert.AreEqual(EncryptionTests.dekProperties, readDekProperties);
        }
Пример #5
0
        /// <summary>
        ///     To get a request without sending a push notification call this method.
        ///     This method will throw an ArgumentException if there is an issue with the input.
        /// </summary>
        /// <param name="subscription">The PushSubscription you wish to send the notification to.</param>
        /// <param name="payload">The payload you wish to send to the user</param>
        /// <param name="options">
        ///     Options for the GCM API key and vapid keys can be passed in if they are unique for each
        ///     notification.
        /// </param>
        /// <returns>A HttpRequestMessage object that can be sent.</returns>
        public HttpRequestMessage GenerateRequestDetails(PushSubscription subscription, string payload,
                                                         Dictionary <string, object> options = null)
        {
            if (!Uri.IsWellFormedUriString(subscription.Endpoint, UriKind.Absolute))
            {
                throw new ArgumentException(@"You must pass in a subscription with at least a valid endpoint");
            }

            var request = new HttpRequestMessage(HttpMethod.Post, subscription.Endpoint);

            if (!string.IsNullOrEmpty(payload) && (string.IsNullOrEmpty(subscription.Auth) ||
                                                   string.IsNullOrEmpty(subscription.P256DH)))
            {
                throw new ArgumentException(
                          @"To send a message with a payload, the subscription must have 'auth' and 'p256dh' keys.");
            }

            var currentGcmApiKey    = _gcmApiKey;
            var currentVapidDetails = _vapidDetails;
            var timeToLive          = DefaultTtl;
            var extraHeaders        = new Dictionary <string, object>();

            if (options != null)
            {
                var validOptionsKeys = new List <string> {
                    "headers", "gcmAPIKey", "vapidDetails", "TTL"
                };
                foreach (var key in options.Keys)
                {
                    if (!validOptionsKeys.Contains(key))
                    {
                        throw new ArgumentException(key + " is an invalid options. The valid options are" +
                                                    string.Join(",", validOptionsKeys));
                    }
                }

                if (options.ContainsKey("headers"))
                {
                    var headers = options["headers"] as Dictionary <string, object>;

                    extraHeaders = headers ?? throw new ArgumentException("options.headers must be of type Dictionary<string,object>");
                }

                if (options.ContainsKey("gcmAPIKey"))
                {
                    var gcmApiKey = options["gcmAPIKey"] as string;

                    currentGcmApiKey = gcmApiKey ?? throw new ArgumentException("options.gcmAPIKey must be of type string");
                }

                if (options.ContainsKey("vapidDetails"))
                {
                    var vapidDetails = options["vapidDetails"] as VapidDetails;
                    currentVapidDetails = vapidDetails ?? throw new ArgumentException("options.vapidDetails must be of type VapidDetails");
                }

                if (options.ContainsKey("TTL"))
                {
                    var ttl = options["TTL"] as int?;
                    if (ttl == null)
                    {
                        throw new ArgumentException("options.TTL must be of type int");
                    }

                    //at this stage ttl cannot be null.
                    timeToLive = (int)ttl;
                }
            }

            string cryptoKeyHeader = null;

            request.Headers.Add("TTL", timeToLive.ToString());

            foreach (var header in extraHeaders)
            {
                request.Headers.Add(header.Key, header.Value.ToString());
            }

            if (!string.IsNullOrEmpty(payload))
            {
                if (string.IsNullOrEmpty(subscription.P256DH) || string.IsNullOrEmpty(subscription.Auth))
                {
                    throw new ArgumentException(
                              @"Unable to send a message with payload to this subscription since it doesn't have the required encryption key");
                }

                var encryptedPayload = TestEncryptor.Encrypt(subscription.P256DH, subscription.Auth, payload);

                request.Content = new ByteArrayContent(encryptedPayload.Payload);
                request.Content.Headers.ContentType   = new MediaTypeHeaderValue("application/octet-stream");
                request.Content.Headers.ContentLength = encryptedPayload.Payload.Length;
                request.Content.Headers.ContentEncoding.Add("aesgcm");
                request.Headers.Add("Encryption", "salt=" + encryptedPayload.Base64EncodeSalt());
                cryptoKeyHeader = @"dh=" + encryptedPayload.Base64EncodePublicKey();
            }
            else
            {
                request.Content = new ByteArrayContent(new byte[0]);
                request.Content.Headers.ContentLength = 0;
            }

            var isGcm = subscription.Endpoint.StartsWith(@"https://android.googleapis.com/gcm/send");
            var isFcm = subscription.Endpoint.StartsWith(@"https://fcm.googleapis.com/fcm/send/");

            if (isGcm)
            {
                if (!string.IsNullOrEmpty(currentGcmApiKey))
                {
                    request.Headers.TryAddWithoutValidation("Authorization", "key=" + currentGcmApiKey);
                }
            }
            else if (currentVapidDetails != null)
            {
                var uri      = new Uri(subscription.Endpoint);
                var audience = uri.Scheme + @"://" + uri.Host;

                var vapidHeaders = VapidHelper.GetVapidHeaders(audience, currentVapidDetails.Subject,
                                                               currentVapidDetails.PublicKey, currentVapidDetails.PrivateKey, currentVapidDetails.Expiration);
                request.Headers.Add(@"Authorization", vapidHeaders["Authorization"]);
                if (string.IsNullOrEmpty(cryptoKeyHeader))
                {
                    cryptoKeyHeader = vapidHeaders["Crypto-Key"];
                }
                else
                {
                    cryptoKeyHeader += @";" + vapidHeaders["Crypto-Key"];
                }
            }
            else if (isFcm && !string.IsNullOrEmpty(currentGcmApiKey))
            {
                request.Headers.TryAddWithoutValidation("Authorization", "key=" + currentGcmApiKey);
            }

            request.Headers.Add("Crypto-Key", cryptoKeyHeader);
            return(request);
        }