Esempio n. 1
0
        //Downloads and decrypts client side encrypted blob, then reuploads blob with server side encryption using an encryption scope with a customer managed key
        private static void EncryptWithCustomerManagedKey(
            string connectionString,
            string containerName,
            string blobName,
            string blobNameAfterMigration,
            string filePath,
            ClientSideEncryptionOptions clientSideOption,
            string encryptionScopeName)
        {
            //Download and decrypt Client Side Encrypted blob using BlobClient with Client Side Encryption Options
            string     downloadFilePath = filePath + ".download";
            BlobClient blobClient       = new BlobClient(
                connectionString,
                containerName,
                blobName).WithClientSideEncryptionOptions(clientSideOption);

            blobClient.DownloadTo(downloadFilePath);

            //Set Blob Client Options with the created Encryption Scope
            BlobClientOptions blobClientOptions = new BlobClientOptions()
            {
                EncryptionScope = encryptionScopeName
            };

            //Reupload Blob with Server Side Encryption
            blobClient = new BlobClient(
                connectionString,
                containerName,
                blobNameAfterMigration,
                blobClientOptions);
            blobClient.Upload(downloadFilePath, true);
        }
        /*Creates example container and client side encrypted blob for sample
         *
         * NOTE: This program requires the following to be stored in the App.Config file:
         * Azure Active Directory Tenant ID - tenantId
         * Service Principal Application ID - clientId
         * Service Principal Password - clientSecret
         * Storage Account Connection String- connectionString
         * Client Side Key Vault Key Uri - clientSideKeyVaultKeyUri
         * Key Wrap Algorithm - keyWrapAlgorithm
         *
         * Creates example objects using names from Constants.cs, which may be edited as needed
         */
        static void Main()
        {
            //Credentials of Service Principal
            TokenCredential credential =
                new ClientSecretCredential(
                    Constants.TenantId,
                    Constants.ClientId,
                    Constants.ClientSecret
                    );

            //Get Uri for Key Vault key
            Uri keyVaultKeyUri = new Uri(Constants.ClientSideKeyVaultKeyUri);
            //Create CryptographyClient using Key Vault Key
            CryptographyClient cryptographyClient = new CryptographyClient(keyVaultKeyUri, credential);
            //Set up Client Side Encryption Options used for Client Side Encryption
            ClientSideEncryptionOptions clientSideOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = cryptographyClient,
                KeyWrapAlgorithm = Constants.KeyWrapAlgorithm
            };

            //Create Blob Service Client
            BlobServiceClient blobServiceClient = new BlobServiceClient(Constants.ConnectionString);

            //Run Setup Function that creates and example container and blob
            SetupForExample(
                blobServiceClient,
                Constants.ContainerName,
                Constants.BlobName,
                clientSideOptions);

            Console.WriteLine("Completed creation of example container and blob");
        }
Esempio n. 3
0
        //Downloads and decrypts client side encrypted blob, then reuploads blob with server side encryption using a customer provided key
        private static void EncryptWithCustomerProvidedKey(
            string connectionString,
            string containerName,
            string blobName,
            string blobNameAfterMigration,
            string filePath,
            ClientSideEncryptionOptions clientSideOption,
            byte[] keyBytes)
        {
            //Download and decrypt Client Side Encrypted blob using BlobClient with Client Side Encryption Options
            string     downloadFilePath = filePath + "download";
            BlobClient blobClient       = new BlobClient(
                connectionString,
                containerName,
                blobName).WithClientSideEncryptionOptions(clientSideOption);

            blobClient.DownloadTo(downloadFilePath);

            //Set Blob Client Options with the given Customer Provided Key
            CustomerProvidedKey customerProvidedKey = new CustomerProvidedKey(keyBytes);
            BlobClientOptions   blobClientOptions   = new BlobClientOptions()
            {
                CustomerProvidedKey = customerProvidedKey,
            };

            //Reupload Blob with Server Side Encryption
            blobClient = new BlobClient(
                connectionString,
                containerName,
                blobNameAfterMigration,
                blobClientOptions);
            blobClient.Upload(downloadFilePath, true);
        }
Esempio n. 4
0
        /*Creates example container, client side encrypted blob, Key Vault key, and encryption scope for sample
         *
         * NOTE: This program requires the following to be stored in the App.Config file:
         * Subscription ID - subscriptionId
         * Resource Group Name - resourceGroup
         * Storage Account Name - storageAccount
         * Storage Account Connection String- connectionString
         *
         * Creates example objects using names from Constants.cs, which may be edited as needed
         */
        public static void SetupForExample(
            BlobServiceClient blobService,
            string containerName,
            string fileName,
            string encryptionScopeName,
            ClientSideEncryptionOptions clientSideOption,
            string keyVaultName,
            string keyVaultKeyName,
            TokenCredential credential
            )
        {
            //Create example Container and .txt file, upload .txt file as client side encrypted blob
            BlobContainerClient containerClient = blobService.CreateBlobContainer(containerName);
            //Create BlobClient with Client Side Encryption Options to upload client side encrypted data
            BlobClient blobClient = containerClient.GetBlobClient(fileName).WithClientSideEncryptionOptions(clientSideOption);

            //Upload blob with client side encryption
            blobClient.Upload(Path.Combine(Constants.SamplePath, Constants.BlobName));
            Console.WriteLine("Uploaded to Blob storage as blob: \n\t {0}\n", blobClient.Uri);

            //Create key and use created key to create encryption scope
            KeyVaultKey keyVaultKey = Setup.CreateKeyVaultKey(keyVaultName, keyVaultKeyName, credential);

            Setup.CreateEncryptionScopeCMK(encryptionScopeName, keyVaultKey.Id);
        }
        /*Creates example container, client side encrypted blob, Key Vault key, and encryption scope for sample
         *
         * NOTE: This program requires the following to be stored in the App.Config file:
         * Subscription ID - subscriptionId
         * Resource Group Name - resourceGroup
         * Storage Account Name - storageAccount
         * Storage Account Connection String- connectionString
         * Key Vault Name - keyVaultName
         *
         * Creates example objects using names from Constants.cs, which may be edited as needed
         */
        static void Main()
        {
            //Creating Key Encryption Key object for Client Side Encryption
            SampleKeyEncryptionKey keyEncryption = new SampleKeyEncryptionKey(Constants.ClientSideCustomerProvidedKey);

            //Set up Client Side Encryption Options used for Client Side Encryption
            ClientSideEncryptionOptions clientSideOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = keyEncryption,
                KeyWrapAlgorithm = Constants.KeyWrapAlgorithm
            };

            //Create Blob Service Client
            BlobServiceClient blobServiceClient = new BlobServiceClient(Constants.ConnectionString);

            //Run Setup Function that creates and example container and blob
            SetupForExample(
                blobServiceClient,
                Constants.ContainerName,
                Constants.BlobName,
                Constants.EncryptionScopeName,
                clientSideOptions);

            Console.WriteLine("Completed creation of example container, blob, and encryption scope");
        }
Esempio n. 6
0
        /// <summary>
        /// Extension method to clone an instance of <see cref="ClientSideEncryptionOptions"/>.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public static ClientSideEncryptionOptions Clone(this ClientSideEncryptionOptions options)
        {
            var newOptions = new ClientSideEncryptionOptions(options.EncryptionVersion);

            CopyOptions(options, newOptions);
            return(newOptions);
        }
Esempio n. 7
0
 public static IClientSideEncryptor GetClientSideEncryptor(this ClientSideEncryptionOptions options)
 {
     return(options.EncryptionVersion switch
     {
         ClientSideEncryptionVersion.V1_0 => new ClientSideEncryptorV1_0(options),
         ClientSideEncryptionVersion.V2_0 => new ClientSideEncryptorV2_0(options),
         _ => throw Errors.ClientSideEncryption.ClientSideEncryptionVersionNotSupported()
     });
Esempio n. 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="QueueServiceClient"/>
 /// class.
 /// </summary>
 /// <param name="serviceUri">
 /// A <see cref="Uri"/> referencing the queue service.
 /// This is likely to be similar to "https://{account_name}.queue.core.windows.net".
 /// </param>
 /// <param name="authentication">
 /// An optional authentication policy used to sign requests.
 /// </param>
 /// <param name="options">
 /// Optional client options that define the transport pipeline
 /// policies for authentication, retries, etc., that are applied to
 /// every request.
 /// </param>
 internal QueueServiceClient(Uri serviceUri, HttpPipelinePolicy authentication, QueueClientOptions options)
 {
     _uri = serviceUri;
     options ??= new QueueClientOptions();
     _pipeline             = options.Build(authentication);
     _version              = options.Version;
     _clientDiagnostics    = new ClientDiagnostics(options);
     _clientSideEncryption = QueueClientSideEncryptionOptions.CloneFrom(options._clientSideEncryptionOptions);
 }
Esempio n. 9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="QueueServiceClient"/>
        /// class.
        /// </summary>
        /// <param name="connectionString">
        /// A connection string includes the authentication information
        /// required for your application to access data in an Azure Storage
        /// account at runtime.
        ///
        /// For more information, see
        /// <see href="https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string">
        /// Configure Azure Storage connection strings</see>.
        /// </param>
        /// <param name="options">
        /// Optional client options that define the transport pipeline
        /// policies for authentication, retries, etc., that are applied to
        /// every request.
        /// </param>
        public QueueServiceClient(string connectionString, QueueClientOptions options)
        {
            var conn = StorageConnectionString.Parse(connectionString);

            _uri = conn.QueueEndpoint;
            options ??= new QueueClientOptions();
            _pipeline             = options.Build(conn.Credentials);
            _version              = options.Version;
            _clientDiagnostics    = new ClientDiagnostics(options);
            _clientSideEncryption = QueueClientSideEncryptionOptions.CloneFrom(options._clientSideEncryptionOptions);
        }
Esempio n. 10
0
 /// <summary>
 /// Rotates the Key Encryption Key (KEK) for a client-side encrypted blob without
 /// needing to reupload the entire blob.
 /// </summary>
 /// <param name="client">
 /// Client to the blob.
 /// </param>
 /// <param name="encryptionOptionsOverride">
 /// Optional override for client-side encryption options to use when updating the key encryption key.
 /// Defaults to the <see cref="ClientSideEncryptionOptions"/> configured on the client when this is
 /// not populated. New key encryption key for the blob will be the
 /// <see cref="ClientSideEncryptionOptions.KeyEncryptionKey"/> on whichever encryption options are
 /// used for the operation. Options must have a resolver that can resolve the old key on the blob.
 /// </param>
 /// <param name="conditions">
 /// Optional request conditions for the operation.
 /// </param>
 /// <param name="cancellationToken">
 /// Cancellation token for the operation.
 /// </param>
 public static async Task UpdateClientSideKeyEncryptionKeyAsync(
     this BlobClient client,
     ClientSideEncryptionOptions encryptionOptionsOverride = default,
     BlobRequestConditions conditions    = default,
     CancellationToken cancellationToken = default)
 => await UpdateClientsideKeyEncryptionKeyInternal(
     client,
     encryptionOptionsOverride,
     conditions,
     async : true,
     cancellationToken).ConfigureAwait(false);
Esempio n. 11
0
 /// <summary>
 /// Rotates the Key Encryption Key (KEK) for a client-side encrypted blob without
 /// needing to reupload the entire blob.
 /// </summary>
 /// <param name="client">
 /// Client to the blob.
 /// </param>
 /// <param name="encryptionOptionsOverride">
 /// Optional override for client-side encryption options to use when updating the key encryption key.
 /// Defaults to the <see cref="ClientSideEncryptionOptions"/> configured on the client when this is
 /// not populated. New key encryption key for the blob will be the
 /// <see cref="ClientSideEncryptionOptions.KeyEncryptionKey"/> on whichever encryption options are
 /// used for the operation. Options must have a resolver that can resolve the old key on the blob.
 /// </param>
 /// <param name="conditions">
 /// Optional request conditions for the operation.
 /// </param>
 /// <param name="cancellationToken">
 /// Cancellation token for the operation.
 /// </param>
 public static void UpdateClientSideKeyEncryptionKey(
     this BlobClient client,
     ClientSideEncryptionOptions encryptionOptionsOverride = default,
     BlobRequestConditions conditions    = default,
     CancellationToken cancellationToken = default)
 => UpdateClientsideKeyEncryptionKeyInternal(
     client,
     encryptionOptionsOverride,
     conditions,
     async: false,
     cancellationToken).EnsureCompleted();
Esempio n. 12
0
        public ClientSideEncryptorV2_0(ClientSideEncryptionOptions options)
        {
            Argument.AssertNotNull(options, nameof(options));
            if (options.EncryptionVersion != ClientSideEncryptionVersion.V2_0)
            {
                Errors.InvalidArgument(nameof(options.EncryptionVersion));
            }

            _keyEncryptionKey = options.KeyEncryptionKey;
            _keyWrapAlgorithm = options.KeyWrapAlgorithm;
        }
Esempio n. 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BlobClient"/>
 /// class.
 /// </summary>
 /// <param name="blobUri">
 /// A <see cref="Uri"/> referencing the blob that includes the
 /// name of the account, the name of the container, and the name of
 /// the blob.
 /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 /// </param>
 /// <param name="pipeline">
 /// The transport pipeline used to send every request.
 /// </param>
 /// <param name="version">
 /// The version of the service to use when sending requests.
 /// </param>
 /// <param name="clientDiagnostics">Client diagnostics.</param>
 /// <param name="customerProvidedKey">Customer provided key.</param>
 /// <param name="clientSideEncryption">Client-side encryption options.</param>
 /// <param name="encryptionScope">Encryption scope.</param>
 internal BlobClient(
     Uri blobUri,
     HttpPipeline pipeline,
     BlobClientOptions.ServiceVersion version,
     ClientDiagnostics clientDiagnostics,
     CustomerProvidedKey?customerProvidedKey,
     ClientSideEncryptionOptions clientSideEncryption,
     string encryptionScope)
     : base(blobUri, pipeline, version, clientDiagnostics, customerProvidedKey, clientSideEncryption, encryptionScope)
 {
 }
        /*
         * Program migrates a client side encrypted blob to server side encryption using Customer Provided Keys
         *
         * NOTE: This program requires the following to be stored in the App.Config file:
         * Azure Active Directory Tenant ID - tenantId
         * Service Principal Application ID - clientId
         * Storage Account Connection String- connectionString
         * Client Side Key Vault Key Uri - clientSideKeyVaultKeyUri
         * Key Wrap Algorithm - keyWrapAlgorithm
         * Container Name - containerName
         * Blob Name - blobName
         * Blob Name After Migration - blobNameAfterMigration
         * Customer Provided Key for Server Side Encryption - serverSideCustomerProvidedKey
         */
        static void Main()
        {
            //Credentials of Service Principal
            TokenCredential credential =
                new ClientSecretCredential(
                    Constants.TenantId,
                    Constants.ClientId,
                    Constants.ClientSecret
                    );

            //Get bytes for customer provided key
            byte[] localKeyBytes = ASCIIEncoding.UTF8.GetBytes(Constants.ServerSideCustomerProvidedKey);

            //File Path for local file used to download and reupload
            string localPath = "./data" + Guid.NewGuid().ToString() + "/";

            Directory.CreateDirectory(localPath);
            string localFilePath = Path.Combine(localPath, Constants.BlobName);

            //Get Uri for Key Vault key
            Uri keyVaultKeyUri = new Uri(Constants.ClientSideKeyVaultKeyUri);
            //Create CryptographyClient using Key Vault Key
            CryptographyClient cryptographyClient = new CryptographyClient(keyVaultKeyUri, credential);
            //Set up Client Side Encryption Options used for Client Side Encryption
            ClientSideEncryptionOptions clientSideOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = cryptographyClient,
                KeyWrapAlgorithm = Constants.KeyWrapAlgorithm
            };

            try
            {
                //Convert Client Side Encryption Blob to Server Side Encrytion with Customer Provided Keys
                EncryptWithCustomerProvidedKey(
                    Constants.ConnectionString,
                    Constants.ContainerName,
                    Constants.BlobName,
                    Constants.BlobNameAfterMigration,
                    localFilePath,
                    clientSideOptions,
                    localKeyBytes);
            }
            finally
            {
                //Delete downloaded files
                CleanUp(localPath);
            }

            Console.WriteLine("Completed migration to Customer Provided Key Server Side Encryption");
        }
Esempio n. 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="QueueServiceClient"/>
 /// class.
 /// </summary>
 /// <param name="serviceUri">
 /// A <see cref="Uri"/> referencing the queue service.
 /// This is likely to be similar to "https://{account_name}.queue.core.windows.net".
 /// </param>
 /// <param name="authentication">
 /// An optional authentication policy used to sign requests.
 /// </param>
 /// <param name="options">
 /// Optional client options that define the transport pipeline
 /// policies for authentication, retries, etc., that are applied to
 /// every request.
 /// </param>
 /// <param name="storageSharedKeyCredential">
 /// The shared key credential used to sign requests.
 /// </param>
 internal QueueServiceClient(
     Uri serviceUri,
     HttpPipelinePolicy authentication,
     QueueClientOptions options,
     StorageSharedKeyCredential storageSharedKeyCredential)
 {
     _uri = serviceUri;
     options ??= new QueueClientOptions();
     _pipeline                   = options.Build(authentication);
     _version                    = options.Version;
     _clientDiagnostics          = new ClientDiagnostics(options);
     _clientSideEncryption       = QueueClientSideEncryptionOptions.CloneFrom(options._clientSideEncryptionOptions);
     _storageSharedKeyCredential = storageSharedKeyCredential;
     _messageEncoding            = options.MessageEncoding;
 }
        //Creates example container and client side encrypted blob for sample
        public static void SetupForExample(
            BlobServiceClient blobService,
            string containerName,
            string fileName,
            ClientSideEncryptionOptions clientSideOption)
        {
            //Create example Container and .txt file, upload .txt file as client side encrypted blob
            BlobContainerClient containerClient = blobService.CreateBlobContainer(containerName);
            //Create BlobClient with Client Side Encryption Options to upload client side encrypted data
            BlobClient blobClient = containerClient.GetBlobClient(fileName).WithClientSideEncryptionOptions(clientSideOption);

            //Upload blob with client side encryption
            blobClient.Upload(Path.Combine(Constants.SamplePath, Constants.BlobName));
            Console.WriteLine("Uploaded to Blob storage as blob: \n\t {0}\n", blobClient.Uri);
        }
        /// <summary>
        /// Creates an encrypted queue client from a normal queue client. Note that this method does not copy over any
        /// client options from the container client. You must pass in your own options. These options will be mutated.
        /// </summary>
        public async Task <DisposingQueue> GetTestEncryptedQueueAsync(
            ClientSideEncryptionOptions encryptionOptions,
            string queueName = default,
            IDictionary <string, string> metadata = default)
        {
            // normally set through property on subclass; this is easier to hook up in current test infra with internals access
            var options = GetOptions();

            options._clientSideEncryptionOptions = encryptionOptions;

            var service = GetServiceClient_SharedKey(options);

            metadata ??= new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            QueueClient queue = InstrumentClient(service.GetQueueClient(GetNewQueueName()));

            return(await DisposingQueue.CreateAsync(queue, metadata));
        }
        private async Task <DisposingContainer> GetTestContainerEncryptionAsync(
            ClientSideEncryptionOptions encryptionOptions,
            string containerName = default,
            IDictionary <string, string> metadata = default)
        {
            // normally set through property on subclass; this is easier to hook up in current test infra with internals access
            var options = GetOptions();

            options._clientSideEncryptionOptions = encryptionOptions;

            containerName ??= GetNewContainerName();
            var service = GetServiceClient_SharedKey(options);

            BlobContainerClient container = InstrumentClient(service.GetBlobContainerClient(containerName));
            await container.CreateAsync(metadata : metadata);

            return(new DisposingContainer(container));
        }
Esempio n. 19
0
        /*
         * Program migrates a client side encrypted blob to server side encryption using customer provided keys
         *
         * NOTE: This program requires the following to be stored in the App.Config file:
         * Storage Account Connection String- connectionString
         * Key Wrap Algorithm for Client Side Encryption - keyWrapAlgorithm
         * Customer Provided Key for Client Side Encryption - clientSideCustomerProvidedKey
         * Container Name - containerName
         * Blob Name - blobName
         * Blob Name After Migration - blobNameAfterMigration
         * Customer Provided Key for Server Side Encryption - serverSideCustomerProvidedKey
         */
        static void Main()
        {
            //Get bytes for customer provided key
            byte[] localKeyBytes = ASCIIEncoding.UTF8.GetBytes(Constants.ServerSideCustomerProvidedKey);

            //File Path for local file used to download and reupload
            string localPath = "./data" + Guid.NewGuid().ToString() + "/";

            Directory.CreateDirectory(localPath);
            string localFilePath = Path.Combine(localPath, Constants.BlobName);

            //Creating Key Encryption Key object for Client Side Encryption
            SampleKeyEncryptionKey keyEncryption = new SampleKeyEncryptionKey(Constants.ClientSideCustomerProvidedKey);

            //Set up Client Side Encryption Options used for Client Side Encryption
            ClientSideEncryptionOptions clientSideOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = keyEncryption,
                KeyWrapAlgorithm = Constants.KeyWrapAlgorithm
            };

            try
            {
                //Convert Client Side Encryption Blob to Server Side Encrytion with Customer Provided Keys
                EncryptWithCustomerProvidedKey(
                    Constants.ConnectionString,
                    Constants.ContainerName,
                    Constants.BlobName,
                    Constants.BlobNameAfterMigration,
                    localFilePath,
                    clientSideOptions,
                    localKeyBytes);
            }
            finally
            {
                //Delete downloaded files
                CleanUp(localPath);
            }

            Console.WriteLine("Completed Migration to Customer Provided Key Server Side Encryption");
        }
        public async Task HashingAndClientSideEncryptionIncompatible(TransactionalHashAlgorithm algorithm)
        {
            await using var disposingContainer = await GetDisposingContainerAsync();

            // Arrange
            const int dataSize = Constants.KB;
            var       data     = GetRandomBuffer(dataSize);

            var hashingOptions = new UploadTransactionalHashingOptions
            {
                Algorithm = algorithm
            };

            var encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = new Mock <Core.Cryptography.IKeyEncryptionKey>().Object,
                KeyWrapAlgorithm = "foo"
            };

            var clientOptions = ClientBuilder.GetOptions();

            clientOptions._clientSideEncryptionOptions = encryptionOptions;

            var client = await GetResourceClientAsync(
                disposingContainer.Container,
                resourceLength : dataSize,
                createResource : true,
                options : clientOptions);

            // Act
            using var stream = new MemoryStream(data);

            var exception = Assert.ThrowsAsync <ArgumentException>(async() => await ParallelUploadAsync(client, stream, hashingOptions, transferOptions: default));

            Assert.AreEqual("Client-side encryption and transactional hashing are not supported at the same time.", exception.Message);
        }
Esempio n. 21
0
        private static async Task UpdateClientsideKeyEncryptionKeyInternal(
            BlobClient client,
            ClientSideEncryptionOptions encryptionOptionsOverride,
            BlobRequestConditions conditions,
            bool async,
            CancellationToken cancellationToken)
        {
            // argument validation
            Argument.AssertNotNull(client, nameof(client));
            ClientSideEncryptionOptions operationEncryptionOptions = encryptionOptionsOverride
                                                                     ?? client.ClientSideEncryption
                                                                     ?? throw new ArgumentException($"{nameof(ClientSideEncryptionOptions)} are not configured on this client and none were provided for the operation.");

            Argument.AssertNotNull(operationEncryptionOptions.KeyEncryptionKey, nameof(ClientSideEncryptionOptions.KeyEncryptionKey));
            Argument.AssertNotNull(operationEncryptionOptions.KeyResolver, nameof(ClientSideEncryptionOptions.KeyResolver));
            Argument.AssertNotNull(operationEncryptionOptions.KeyWrapAlgorithm, nameof(ClientSideEncryptionOptions.KeyWrapAlgorithm));

            using (client.ClientConfiguration.Pipeline.BeginLoggingScope(nameof(BlobClient)))
            {
                client.ClientConfiguration.Pipeline.LogMethodEnter(
                    nameof(BlobBaseClient),
                    message:
                    $"{nameof(Uri)}: {client.Uri}\n" +
                    $"{nameof(conditions)}: {conditions}");

                DiagnosticScope scope = client.ClientConfiguration.ClientDiagnostics.CreateScope($"{nameof(BlobClient)}.{nameof(UpdateClientSideKeyEncryptionKey)}");

                try
                {
                    // hold onto etag, metadata, encryptiondata
                    BlobProperties getPropertiesResponse = await client.GetPropertiesInternal(conditions, async, cancellationToken).ConfigureAwait(false);

                    ETag etag = getPropertiesResponse.ETag;
                    IDictionary <string, string> metadata = getPropertiesResponse.Metadata;
                    EncryptionData encryptionData         = BlobClientSideDecryptor.GetAndValidateEncryptionDataOrDefault(metadata)
                                                            ?? throw new InvalidOperationException("Resource has no client-side encryption key to rotate.");

                    // rotate keywrapping
                    byte[] newWrappedKey = await WrapKeyInternal(
                        await UnwrapKeyInternal(
                            encryptionData,
                            operationEncryptionOptions.KeyResolver,
                            async,
                            cancellationToken).ConfigureAwait(false),
                        operationEncryptionOptions.KeyWrapAlgorithm,
                        operationEncryptionOptions.KeyEncryptionKey,
                        async,
                        cancellationToken).ConfigureAwait(false);

                    // set new wrapped key info and reinsert into metadata
                    encryptionData.WrappedContentKey = new KeyEnvelope
                    {
                        EncryptedKey = newWrappedKey,
                        Algorithm    = operationEncryptionOptions.KeyWrapAlgorithm,
                        KeyId        = operationEncryptionOptions.KeyEncryptionKey.KeyId
                    };
                    metadata[Constants.ClientSideEncryption.EncryptionDataKey] = EncryptionDataSerializer.Serialize(encryptionData);

                    // update blob ONLY IF ETAG MATCHES (do not take chances encryption info is now out of sync)
                    BlobRequestConditions modifiedRequestConditions = BlobRequestConditions.CloneOrDefault(conditions) ?? new BlobRequestConditions();
                    modifiedRequestConditions.IfMatch = etag;
                    await client.SetMetadataInternal(metadata, modifiedRequestConditions, async, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    client.ClientConfiguration.Pipeline.LogException(ex);
                    scope.Failed(ex);
                    throw;
                }
                finally
                {
                    client.ClientConfiguration.Pipeline.LogMethodExit(nameof(BlobBaseClient));
                    scope.Dispose();
                }
            }
        }
Esempio n. 22
0
 /// <summary>
 /// Copies all properties from one instance to another. It cannot copy
 /// <see cref="ClientSideEncryptionOptions.EncryptionVersion"/>;
 /// that is the responsibility of the caller who made the instance.
 /// </summary>
 /// <param name="source">Object to copy from.</param>
 /// <param name="destination">Object to copy to.</param>
 /// <remarks>
 /// This functionality has been pulled out to be accessible by other
 /// clone methods available on subclasses. They need the ability to
 /// instantiate the subclass destination first before copying over the
 /// properties.
 /// </remarks>
 internal static void CopyOptions(ClientSideEncryptionOptions source, ClientSideEncryptionOptions destination)
 {
     destination.KeyEncryptionKey = source.KeyEncryptionKey;
     destination.KeyResolver      = source.KeyResolver;
     destination.KeyWrapAlgorithm = source.KeyWrapAlgorithm;
 }
Esempio n. 23
0
 /// <summary>
 /// Clones the given <see cref="ClientSideEncryptionOptions"/> as an instance of
 /// <see cref="QueueClientSideEncryptionOptions"/>. If the given instance is also a
 /// <see cref="QueueClientSideEncryptionOptions"/>, this clones it's specialty data as well.
 /// </summary>
 /// <returns></returns>
 internal static QueueClientSideEncryptionOptions CloneFrom(ClientSideEncryptionOptions options)
 {
     if (options == default)
     {
         return(default);
 public ClientSideDecryptor(ClientSideEncryptionOptions options)
 {
     _potentialCachedIKeyEncryptionKey = options.KeyEncryptionKey;
     _keyResolver = options.KeyResolver;
 }
 public ClientSideEncryptor(ClientSideEncryptionOptions options)
 {
     _keyEncryptionKey = options.KeyEncryptionKey;
     _keyWrapAlgorithm = options.KeyWrapAlgorithm;
 }