Example #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);
            }
        }
Example #2
0
 // A non-public constructor to ensure the factory is used to create the object.
 // This will prevent memory leaks when handling the HttpResponseMessage.
 internal DataEncryptionKeyResponse(
     HttpStatusCode httpStatusCode,
     Headers headers,
     DataEncryptionKeyProperties keyProperties,
     DataEncryptionKey key,
     CosmosDiagnostics diagnostics)
 {
     this.StatusCode        = httpStatusCode;
     this.Headers           = headers;
     this.Resource          = keyProperties;
     this.DataEncryptionKey = key;
     this.Diagnostics       = diagnostics;
 }
Example #3
0
 internal Task <DataEncryptionKeyResponse> CreateDataEncryptionKeyResponseAsync(
     DataEncryptionKey dataEncryptionKey,
     Task <ResponseMessage> cosmosResponseMessageTask)
 {
     return(this.ProcessMessageAsync(cosmosResponseMessageTask, (cosmosResponseMessage) =>
     {
         DataEncryptionKeyProperties dekProperties = this.ToObjectInternal <DataEncryptionKeyProperties>(cosmosResponseMessage);
         return new DataEncryptionKeyResponse(
             cosmosResponseMessage.StatusCode,
             cosmosResponseMessage.Headers,
             dekProperties,
             dataEncryptionKey,
             cosmosResponseMessage.Diagnostics);
     }));
 }
Example #4
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();
        }
        public async Task <Stream> EncryptAsync(
            Stream input,
            EncryptionOptions encryptionOptions,
            DatabaseCore database,
            EncryptionKeyWrapProvider encryptionKeyWrapProvider,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            Debug.Assert(input != null);
            Debug.Assert(encryptionOptions != null);
            Debug.Assert(database != null);
            Debug.Assert(diagnosticsContext != null);

            if (encryptionOptions.PathsToEncrypt == null)
            {
                throw new ArgumentNullException(nameof(encryptionOptions.PathsToEncrypt));
            }

            if (encryptionOptions.PathsToEncrypt.Count == 0)
            {
                return(input);
            }

            foreach (string path in encryptionOptions.PathsToEncrypt)
            {
                if (string.IsNullOrEmpty(path) || path[0] != '/' || path.LastIndexOf('/') != 0)
                {
                    throw new ArgumentException($"Invalid path {path ?? string.Empty}", nameof(encryptionOptions.PathsToEncrypt));
                }
            }

            if (encryptionOptions.DataEncryptionKey == null)
            {
                throw new ArgumentException("Invalid encryption options", nameof(encryptionOptions.DataEncryptionKey));
            }

            if (encryptionKeyWrapProvider == null)
            {
                throw new ArgumentException(ClientResources.EncryptionKeyWrapProviderNotConfigured);
            }

            DataEncryptionKey dek = database.GetDataEncryptionKey(encryptionOptions.DataEncryptionKey.Id);

            DataEncryptionKeyCore dekCore = (DataEncryptionKeyInlineCore)dek;

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

            JObject itemJObj = EncryptionProcessor.baseSerializer.FromStream <JObject>(input);

            JObject toEncryptJObj = new JObject();

            foreach (string pathToEncrypt in encryptionOptions.PathsToEncrypt)
            {
                string propertyName        = pathToEncrypt.Substring(1);
                JToken propertyValueHolder = itemJObj.Property(propertyName).Value;

                // Even null in the JSON is a JToken with Type Null, this null check is just a sanity check
                if (propertyValueHolder != null)
                {
                    toEncryptJObj.Add(propertyName, itemJObj.Property(propertyName).Value.Value <JToken>());
                    itemJObj.Remove(propertyName);
                }
            }

            MemoryStream memoryStream = EncryptionProcessor.baseSerializer.ToStream <JObject>(toEncryptJObj) as MemoryStream;

            Debug.Assert(memoryStream != null);
            Debug.Assert(memoryStream.TryGetBuffer(out _));

            byte[] plainText = memoryStream.GetBuffer();

            EncryptionProperties encryptionProperties = new EncryptionProperties(
                dataEncryptionKeyRid: dekProperties.ResourceId,
                encryptionFormatVersion: 1,
                encryptedData: inMemoryRawDek.AlgorithmUsingRawDek.EncryptData(plainText));

            itemJObj.Add(Constants.Properties.EncryptedInfo, JObject.FromObject(encryptionProperties));
            return(EncryptionProcessor.baseSerializer.ToStream(itemJObj));
        }