Braedon-Wooding-Displayr commented on code in PR #742:
URL: 
https://github.com/apache/arrow-rs-object-store/pull/742#discussion_r3409218343


##########
src/azure/client.rs:
##########
@@ -190,6 +220,97 @@ impl AzureConfig {
     }
 }
 
+/// Encryption headers for Azure requests.
+/// Azure only supports AES256 encryption with customer-provided keys.
+#[derive(Default, Clone)]
+pub(crate) struct AzureEncryptionHeaders {
+    pub encryption_key: Option<String>,
+    pub encryption_key_sha256: Option<String>,
+}
+
+impl std::fmt::Debug for AzureEncryptionHeaders {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("AzureEncryptionHeaders")
+            .field("key_configured", &self.encryption_key.is_some())
+            .finish()
+    }
+}
+
+impl AzureEncryptionHeaders {
+    pub(crate) fn try_new(encryption_key: Option<String>) -> Result<Self> {
+        let Some(encryption_key) = encryption_key else {
+            return Ok(Self::default());
+        };
+
+        let decoded_key = BASE64_STANDARD
+            .decode(encryption_key.as_bytes())
+            .map_err(|source| crate::Error::Generic {
+                store: STORE,
+                source: Box::new(source),
+            })?;
+
+        // As above encryption keys must be 256-bit AES keys,
+        // which means the base64-encoded value must decode to 32 bytes.
+        if decoded_key.len() != 32 {
+            return Err(crate::Error::Generic {
+                store: STORE,
+                source: format!(
+                    "Azure customer-provided encryption key must decode to 32 
bytes, got {}",
+                    decoded_key.len()
+                )
+                .into(),
+            });
+        }
+
+        let encryption_key_sha256 =
+            BASE64_STANDARD.encode(digest::digest(&digest::SHA256, 
&decoded_key));
+
+        Ok(Self {
+            encryption_key: Some(encryption_key),
+            encryption_key_sha256: Some(encryption_key_sha256),
+        })
+    }
+
+    fn is_enabled(&self) -> bool {
+        self.encryption_key.is_some()
+    }
+}
+
+/// Request-builder extension for customer-provided encryption keys (CPK).
+///
+/// Mirrors [`CredentialExt`] so that CPK headers are applied as part of the
+/// fluent request-construction chain, keeping the secret key material close to
+/// the rest of the request building rather than as a detached side-call.
+pub(crate) trait EncryptionHeadersExt {
+    /// Apply the customer-provided encryption headers for the request target.
+    fn with_azure_encryption_headers(self, headers: &AzureEncryptionHeaders) 
-> Self;
+
+    /// Apply the customer-provided encryption headers for a copy *source*.

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to