Exemple #1
0
        public async Task EncryptionUTRewrapDekWithoutEncryptionSerializer()
        {
            string dekId = "mydek";
            EncryptionTestHandler testHandler = new EncryptionTestHandler();

            // Create a DEK using a properly setup client first
            Container    container = this.GetContainerWithMockSetup(testHandler);
            DatabaseCore databaseWithSerializer = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            DataEncryptionKeyResponse dekResponse = await databaseWithSerializer.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            Assert.AreEqual(HttpStatusCode.Created, dekResponse.StatusCode);

            // Clear the handler pipeline that would have got setup
            testHandler.InnerHandler = null;

            // Ensure rewrap for this key fails on improperly configured client
            try
            {
                DatabaseCore      database = (DatabaseCore)((ContainerCore)(ContainerInlineCore)this.GetContainer(testHandler)).Database;
                DataEncryptionKey dek      = database.GetDataEncryptionKey(dekId);
                await dek.RewrapAsync(this.metadata2);

                Assert.Fail();
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual(ClientResources.EncryptionKeyWrapProviderNotConfigured, ex.Message);
            }
        }
Exemple #2
0
        /// <inheritdoc/>
        public override async Task <DataEncryptionKeyResponse> ReadAsync(
            RequestOptions requestOptions       = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            DataEncryptionKeyResponse response = await this.ReadInternalAsync(requestOptions, diagnosticsContext : null, cancellationToken : cancellationToken);

            this.ClientContext.DekCache.Set(this.Database.Id, this.LinkUri, response.Resource);
            return(response);
        }
        async Task <DataEncryptionKeyResponse> CreateDataEncryptionKeyAsync(
            string id,
            CosmosEncryptionAlgorithm encryptionAlgorithmId,
            EncryptionKeyWrapMetadata encryptionKeyWrapMetadata,
            RequestOptions requestOptions       = null,
            CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(id))
            {
                throw new ArgumentNullException(nameof(id));
            }

            if (encryptionAlgorithmId != CosmosEncryptionAlgorithm.AE_AES_256_CBC_HMAC_SHA_256_RANDOMIZED)
            {
                throw new ArgumentException(string.Format("Unsupported Encryption Algorithm {0}", encryptionAlgorithmId), nameof(encryptionAlgorithmId));
            }

            if (encryptionKeyWrapMetadata == null)
            {
                throw new ArgumentNullException(nameof(encryptionKeyWrapMetadata));
            }

            this.ClientContext.ValidateResource(id);

            DataEncryptionKeyCore newDek = (DataEncryptionKeyInlineCore)this.GetDataEncryptionKey(id);

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            byte[] rawDek = newDek.GenerateKey(encryptionAlgorithmId);

            (byte[] wrappedDek, EncryptionKeyWrapMetadata updatedMetadata, InMemoryRawDek inMemoryRawDek) = await newDek.WrapAsync(
                rawDek,
                encryptionAlgorithmId,
                encryptionKeyWrapMetadata,
                diagnosticsContext,
                cancellationToken);

            DataEncryptionKeyProperties dekProperties = new DataEncryptionKeyProperties(id, encryptionAlgorithmId, wrappedDek, updatedMetadata);
            Stream streamPayload = this.ClientContext.SerializerCore.ToStream(dekProperties);
            Task <ResponseMessage> responseMessage = this.CreateDataEncryptionKeyStreamAsync(
                streamPayload,
                requestOptions,
                cancellationToken);

            DataEncryptionKeyResponse dekResponse = await this.ClientContext.ResponseFactory.CreateDataEncryptionKeyResponseAsync(newDek, responseMessage);

            Debug.Assert(dekResponse.Resource != null);

            this.ClientContext.DekCache.Set(this.Id, newDek.LinkUri, dekResponse.Resource);
            this.ClientContext.DekCache.SetRawDek(dekResponse.Resource.SelfLink, inMemoryRawDek);
            return(dekResponse);
        }
Exemple #4
0
        /// <inheritdoc/>
        public override async Task <DataEncryptionKeyResponse> RewrapAsync(
            EncryptionKeyWrapMetadata newWrapMetadata,
            RequestOptions requestOptions       = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (newWrapMetadata == null)
            {
                throw new ArgumentNullException(nameof(newWrapMetadata));
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            (DataEncryptionKeyProperties dekProperties, InMemoryRawDek inMemoryRawDek) = await this.FetchUnwrappedAsync(
                diagnosticsContext,
                cancellationToken);

            (byte[] wrappedDek, EncryptionKeyWrapMetadata updatedMetadata, InMemoryRawDek updatedRawDek) = await this.WrapAsync(
                inMemoryRawDek.RawDek,
                dekProperties.EncryptionAlgorithmId,
                newWrapMetadata,
                diagnosticsContext,
                cancellationToken);

            if (requestOptions == null)
            {
                requestOptions = new RequestOptions();
            }

            requestOptions.IfMatchEtag = dekProperties.ETag;

            DataEncryptionKeyProperties newDekProperties = new DataEncryptionKeyProperties(dekProperties);

            newDekProperties.WrappedDataEncryptionKey  = wrappedDek;
            newDekProperties.EncryptionKeyWrapMetadata = updatedMetadata;

            Task <ResponseMessage> responseMessage = this.ProcessStreamAsync(
                this.ClientContext.SerializerCore.ToStream(newDekProperties),
                OperationType.Replace,
                requestOptions,
                diagnosticsContext,
                cancellationToken);

            DataEncryptionKeyResponse response = await this.ClientContext.ResponseFactory.CreateDataEncryptionKeyResponseAsync(this, responseMessage);

            Debug.Assert(response.Resource != null);

            this.ClientContext.DekCache.Set(this.Database.Id, this.LinkUri, response.Resource);
            this.ClientContext.DekCache.SetRawDek(response.Resource.ResourceId, updatedRawDek);
            return(response);
        }
Exemple #5
0
        public async Task EncryptionUTReadItem()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            string dekId = "mydek";
            DataEncryptionKeyResponse dekResponse = await database.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            Assert.AreEqual(HttpStatusCode.Created, dekResponse.StatusCode);
            MyItem item = await EncryptionUnitTests.CreateItemAsync(container, dekId, MyItem.PathsToEncrypt);

            ItemResponse <MyItem> readResponse = await container.ReadItemAsync <MyItem>(item.Id, new PartitionKey(item.PK));

            Assert.AreEqual(item, readResponse.Resource);
        }
Exemple #6
0
        public async Task EncryptionUTRewrapDek()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            string dekId = "mydek";
            DataEncryptionKeyResponse createResponse = await database.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            DataEncryptionKeyProperties createdProperties = createResponse.Resource;

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);
            this.VerifyWrap(this.dek, this.metadata1);

            DataEncryptionKey         dek            = database.GetDataEncryptionKey(dekId);
            DataEncryptionKeyResponse rewrapResponse = await dek.RewrapAsync(this.metadata2);

            DataEncryptionKeyProperties rewrappedProperties = rewrapResponse.Resource;

            Assert.IsNotNull(rewrappedProperties);

            Assert.AreEqual(dekId, rewrappedProperties.Id);
            Assert.AreEqual(createdProperties.CreatedTime, rewrappedProperties.CreatedTime);
            Assert.IsNotNull(rewrappedProperties.LastModified);
            Assert.AreEqual(createdProperties.ResourceId, rewrappedProperties.ResourceId);
            Assert.AreEqual(createdProperties.SelfLink, rewrappedProperties.SelfLink);

            IEnumerable <byte> expectedRewrappedKey = this.dek.Select(b => (byte)(b + 2));

            Assert.IsTrue(expectedRewrappedKey.SequenceEqual(rewrappedProperties.WrappedDataEncryptionKey));

            Assert.AreEqual(new EncryptionKeyWrapMetadata(this.metadata2.Value + this.metadataUpdateSuffix), rewrappedProperties.EncryptionKeyWrapMetadata);

            Assert.AreEqual(2, this.testHandler.Received.Count);
            RequestMessage rewrapRequestMessage = this.testHandler.Received[1];

            Assert.AreEqual(ResourceType.ClientEncryptionKey, rewrapRequestMessage.ResourceType);
            Assert.AreEqual(OperationType.Replace, rewrapRequestMessage.OperationType);
            Assert.AreEqual(createResponse.ETag, rewrapRequestMessage.Headers[HttpConstants.HttpHeaders.IfMatch]);

            Assert.IsTrue(this.testHandler.Deks.ContainsKey(dekId));
            DataEncryptionKeyProperties serverDekProperties = this.testHandler.Deks[dekId];

            Assert.IsTrue(serverDekProperties.Equals(rewrappedProperties));

            this.VerifyWrap(this.dek, this.metadata2);
            this.mockKeyWrapProvider.VerifyNoOtherCalls();
        }
Exemple #7
0
        private async Task <DataEncryptionKeyResponse> ReadInternalAsync(
            RequestOptions requestOptions,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            Task <ResponseMessage> responseMessage = this.ProcessStreamAsync(
                streamPayload: null,
                operationType: OperationType.Read,
                requestOptions: requestOptions,
                diagnosticsContext: diagnosticsContext,
                cancellationToken: cancellationToken);

            DataEncryptionKeyResponse response = await this.ClientContext.ResponseFactory.CreateDataEncryptionKeyResponseAsync(this, responseMessage);

            Debug.Assert(response.Resource != null);
            return(response);
        }
Exemple #8
0
        private async Task <DataEncryptionKeyProperties> ReadResourceByRidSelfLinkAsync(
            string ridSelfLink,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Task <ResponseMessage> responseMessage = this.ClientContext.ProcessResourceOperationStreamAsync(
                resourceUri: new Uri(ridSelfLink, UriKind.Relative),
                resourceType: ResourceType.ClientEncryptionKey,
                operationType: OperationType.Read,
                cosmosContainerCore: null,
                partitionKey: null,
                streamPayload: null,
                requestOptions: null,
                requestEnricher: null,
                diagnosticsScope: diagnosticsContext,
                cancellationToken: cancellationToken);

            DataEncryptionKeyResponse response = await this.ClientContext.ResponseFactory.CreateDataEncryptionKeyResponseAsync(this, responseMessage);

            Debug.Assert(response.Resource != null);
            return(response);
        }
Exemple #9
0
        public async Task EncryptionUTCreateItem()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            string dekId = "mydek";
            DataEncryptionKeyResponse dekResponse = await database.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            Assert.AreEqual(HttpStatusCode.Created, dekResponse.StatusCode);
            MyItem item = await EncryptionUnitTests.CreateItemAsync(container, dekId, MyItem.PathsToEncrypt);

            // Validate server state
            Assert.IsTrue(this.testHandler.Items.TryGetValue(item.Id, out JObject serverItem));
            Assert.IsNotNull(serverItem);
            Assert.AreEqual(item.Id, serverItem.Property(Constants.Properties.Id).Value.Value <string>());
            Assert.AreEqual(item.PK, serverItem.Property(nameof(MyItem.PK)).Value.Value <string>());
            Assert.IsNull(serverItem.Property(nameof(MyItem.EncStr1)));
            Assert.IsNull(serverItem.Property(nameof(MyItem.EncInt)));

            JProperty eiJProp = serverItem.Property(Constants.Properties.EncryptedInfo);

            Assert.IsNotNull(eiJProp);
            Assert.IsNotNull(eiJProp.Value);
            Assert.AreEqual(JTokenType.Object, eiJProp.Value.Type);
            EncryptionProperties encryptionPropertiesAtServer = ((JObject)eiJProp.Value).ToObject <EncryptionProperties>();

            Assert.IsNotNull(encryptionPropertiesAtServer);
            Assert.AreEqual(dekResponse.Resource.ResourceId, encryptionPropertiesAtServer.DataEncryptionKeyRid);
            Assert.AreEqual(1, encryptionPropertiesAtServer.EncryptionFormatVersion);
            Assert.IsNotNull(encryptionPropertiesAtServer.EncryptedData);

            JObject decryptedJObj = EncryptionUnitTests.ParseStream(new MemoryStream(encryptionPropertiesAtServer.EncryptedData.Reverse().ToArray()));

            Assert.AreEqual(2, decryptedJObj.Properties().Count());
            Assert.AreEqual(item.EncStr1, decryptedJObj.Property(nameof(MyItem.EncStr1)).Value.Value <string>());
            Assert.AreEqual(item.EncInt, decryptedJObj.Property(nameof(MyItem.EncInt)).Value.Value <int>());
        }
Exemple #10
0
        public async Task EncryptionUTCreateDek()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            string dekId = "mydek";
            DataEncryptionKeyResponse dekResponse = await database.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            Assert.AreEqual(HttpStatusCode.Created, dekResponse.StatusCode);
            Assert.AreEqual(requestCharge, dekResponse.RequestCharge);
            Assert.IsNotNull(dekResponse.ETag);

            DataEncryptionKeyProperties dekProperties = dekResponse.Resource;

            Assert.IsNotNull(dekProperties);
            Assert.AreEqual(dekResponse.ETag, dekProperties.ETag);
            Assert.AreEqual(dekId, dekProperties.Id);

            Assert.AreEqual(1, this.testHandler.Received.Count);
            RequestMessage createDekRequestMessage = this.testHandler.Received[0];

            Assert.AreEqual(ResourceType.ClientEncryptionKey, createDekRequestMessage.ResourceType);
            Assert.AreEqual(OperationType.Create, createDekRequestMessage.OperationType);

            Assert.IsTrue(this.testHandler.Deks.ContainsKey(dekId));
            DataEncryptionKeyProperties serverDekProperties = this.testHandler.Deks[dekId];

            Assert.IsTrue(serverDekProperties.Equals(dekProperties));

            // Make sure we didn't push anything else in the JSON (such as raw DEK) by comparing JSON properties
            // to properties exposed in DataEncryptionKeyProperties.
            createDekRequestMessage.Content.Position = 0; // it is a test assumption that the client uses MemoryStream
            JObject jObj = JObject.Parse(await new StreamReader(createDekRequestMessage.Content).ReadToEndAsync());
            IEnumerable <string> dekPropertiesPropertyNames = GetJsonPropertyNamesForType(typeof(DataEncryptionKeyProperties));

            foreach (JProperty property in jObj.Properties())
            {
                Assert.IsTrue(dekPropertiesPropertyNames.Contains(property.Name));
            }

            // Key wrap metadata should be the only "object" child in the JSON (given current properties in DataEncryptionKeyProperties)
            IEnumerable <JToken> objectChildren = jObj.PropertyValues().Where(v => v.Type == JTokenType.Object);

            Assert.AreEqual(1, objectChildren.Count());
            JObject keyWrapMetadataJObj = (JObject)objectChildren.First();

            Assert.AreEqual(Constants.Properties.KeyWrapMetadata, ((JProperty)keyWrapMetadataJObj.Parent).Name);

            IEnumerable <string> keyWrapMetadataPropertyNames = GetJsonPropertyNamesForType(typeof(EncryptionKeyWrapMetadata));

            foreach (JProperty property in keyWrapMetadataJObj.Properties())
            {
                Assert.IsTrue(keyWrapMetadataPropertyNames.Contains(property.Name));
            }

            IEnumerable <byte> expectedWrappedKey = this.VerifyWrap(this.dek, this.metadata1);

            this.mockKeyWrapProvider.VerifyNoOtherCalls();

            Assert.IsTrue(expectedWrappedKey.SequenceEqual(dekProperties.WrappedDataEncryptionKey));
        }