-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat: Making From<ConfigFileDecryptionProperties/ConfigFileEncryptionProperties> conversions fallible with TryFrom
#21985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
94d658b
854d6b8
84da70f
552abe7
acc50e6
2ae481e
9d21471
f84b281
c7f4b0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2862,28 +2862,42 @@ impl ConfigField for ConfigFileEncryptionProperties { | |
| } | ||
|
|
||
| #[cfg(feature = "parquet_encryption")] | ||
| impl From<ConfigFileEncryptionProperties> for FileEncryptionProperties { | ||
| fn from(val: ConfigFileEncryptionProperties) -> Self { | ||
| impl TryFrom<ConfigFileEncryptionProperties> for FileEncryptionProperties { | ||
| type Error = DataFusionError; | ||
|
|
||
| fn try_from(val: ConfigFileEncryptionProperties) -> Result<Self> { | ||
| let mut fep = FileEncryptionProperties::builder( | ||
| hex::decode(val.footer_key_as_hex).unwrap(), | ||
| hex::decode(val.footer_key_as_hex) | ||
| .map_err(|e| { | ||
| DataFusionError::Configuration(format!("Unable to decode hex footer key from ConfigFileEncryptionProperties: {e}")) | ||
| })?, | ||
| ) | ||
| .with_plaintext_footer(!val.encrypt_footer) | ||
| .with_aad_prefix_storage(val.store_aad_prefix); | ||
|
|
||
| if !val.footer_key_metadata_as_hex.is_empty() { | ||
| fep = fep.with_footer_key_metadata( | ||
| hex::decode(&val.footer_key_metadata_as_hex) | ||
| .expect("Invalid footer key metadata"), | ||
| .map_err(|e| { | ||
| DataFusionError::Configuration(format!("Unable to decode hex footer key metadata from ConfigFileEncryptionProperties: {e}")) | ||
| })?, | ||
| ); | ||
| } | ||
|
|
||
| for (column_name, encryption_props) in val.column_encryption_properties.iter() { | ||
| let encryption_key = hex::decode(&encryption_props.column_key_as_hex) | ||
| .expect("Invalid column encryption key"); | ||
| .map_err(|e| { | ||
| DataFusionError::Configuration(format!("Unable to decode hex encryption key metadata for column {column_name}: {e}")) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. message says "encryption key metadata", but this is decoding the actual column encryption key. Please change it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops sorry ! 😄
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed |
||
| })?; | ||
| let key_metadata = encryption_props | ||
| .column_metadata_as_hex | ||
| .as_ref() | ||
| .map(|x| hex::decode(x).expect("Invalid column metadata")); | ||
| .map(hex::decode) | ||
| .transpose() | ||
| .map_err(|e| { | ||
| DataFusionError::Configuration(format!("Unable to decode hex column metadata for column {column_name}: {e}")) | ||
| })?; | ||
|
|
||
| match key_metadata { | ||
| Some(key_metadata) => { | ||
| fep = fep.with_column_key_and_metadata( | ||
|
|
@@ -2899,11 +2913,18 @@ impl From<ConfigFileEncryptionProperties> for FileEncryptionProperties { | |
| } | ||
|
|
||
| if !val.aad_prefix_as_hex.is_empty() { | ||
| let aad_prefix: Vec<u8> = | ||
| hex::decode(&val.aad_prefix_as_hex).expect("Invalid AAD prefix"); | ||
| let aad_prefix: Vec<u8> = hex::decode(&val.aad_prefix_as_hex).map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Unable to decode hex AAD prefix from ConfigFileEncryptionProperties: {e}" | ||
| )) | ||
| })?; | ||
| fep = fep.with_aad_prefix(aad_prefix); | ||
| } | ||
| Arc::unwrap_or_clone(fep.build().unwrap()) | ||
| Ok(Arc::unwrap_or_clone(fep.build().map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Could not build FileEncryptionProperties: {e}" | ||
| )) | ||
| })?)) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -3019,36 +3040,54 @@ impl ConfigField for ConfigFileDecryptionProperties { | |
| } | ||
|
|
||
| #[cfg(feature = "parquet_encryption")] | ||
| impl From<ConfigFileDecryptionProperties> for FileDecryptionProperties { | ||
| fn from(val: ConfigFileDecryptionProperties) -> Self { | ||
| impl TryFrom<ConfigFileDecryptionProperties> for FileDecryptionProperties { | ||
| type Error = DataFusionError; | ||
|
|
||
| fn try_from(val: ConfigFileDecryptionProperties) -> Result<Self> { | ||
| let mut column_names: Vec<&str> = Vec::new(); | ||
| let mut column_keys: Vec<Vec<u8>> = Vec::new(); | ||
|
|
||
| for (col_name, decryption_properties) in val.column_decryption_properties.iter() { | ||
| let column_key_as_hex = hex::decode(&decryption_properties.column_key_as_hex).map_err(|e| { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| DataFusionError::Configuration(format! | ||
| ("Could not decode hex column key from ConfigFileDecryptionProperties for column name {col_name}: {e}.")) | ||
| })?; | ||
| column_names.push(col_name.as_str()); | ||
| column_keys.push( | ||
| hex::decode(&decryption_properties.column_key_as_hex) | ||
| .expect("Invalid column decryption key"), | ||
| ); | ||
| column_keys.push(column_key_as_hex); | ||
| } | ||
|
|
||
| let mut fep = FileDecryptionProperties::builder( | ||
| hex::decode(val.footer_key_as_hex).expect("Invalid footer key"), | ||
| ) | ||
| .with_column_keys(column_names, column_keys) | ||
| .unwrap(); | ||
| let footer_key = hex::decode(val.footer_key_as_hex).map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Could not decode hex footer key from ConfigFileDecryptionProperties: {e}." | ||
| )) | ||
| })?; | ||
|
|
||
| let mut fep = FileDecryptionProperties::builder(footer_key) | ||
| .with_column_keys(column_names, column_keys) | ||
| .map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Could not set column keys on FileDecryptionPropertiesBuilder: {e}." | ||
| )) | ||
| })?; | ||
|
|
||
| if !val.footer_signature_verification { | ||
| fep = fep.disable_footer_signature_verification(); | ||
| } | ||
|
|
||
| if !val.aad_prefix_as_hex.is_empty() { | ||
| let aad_prefix = | ||
| hex::decode(&val.aad_prefix_as_hex).expect("Invalid AAD prefix"); | ||
| let aad_prefix = hex::decode(&val.aad_prefix_as_hex).map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Could not decode hex AAD prefix from ConfigFileDecryptionProperties: {e}." | ||
| )) | ||
| })?; | ||
| fep = fep.with_aad_prefix(aad_prefix); | ||
| } | ||
|
|
||
| Arc::unwrap_or_clone(fep.build().unwrap()) | ||
| Ok(Arc::unwrap_or_clone(fep.build().map_err(|e| { | ||
| DataFusionError::Configuration(format!( | ||
| "Could not build FileDecryptionProperties: {e}." | ||
| )) | ||
| })?)) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -3586,13 +3625,13 @@ mod tests { | |
| let config_encrypt = | ||
| ConfigFileEncryptionProperties::from(&file_encryption_properties); | ||
| let encryption_properties_built = | ||
| Arc::new(FileEncryptionProperties::from(config_encrypt.clone())); | ||
| Arc::new(FileEncryptionProperties::try_from(config_encrypt.clone()).unwrap()); | ||
| assert_eq!(file_encryption_properties, encryption_properties_built); | ||
|
|
||
| let config_decrypt = | ||
| ConfigFileDecryptionProperties::try_from(&decryption_properties).unwrap(); | ||
| let decryption_properties_built = | ||
| Arc::new(FileDecryptionProperties::from(config_decrypt.clone())); | ||
| Arc::new(FileDecryptionProperties::try_from(config_decrypt.clone()).unwrap()); | ||
| assert_eq!(decryption_properties, decryption_properties_built); | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////////// | ||
|
|
@@ -3678,6 +3717,126 @@ mod tests { | |
| ); | ||
| } | ||
|
|
||
| #[cfg(feature = "parquet_encryption")] | ||
| #[test] | ||
| fn parquet_encryption_invalid_hex_errors_encryption() { | ||
| use crate::config::ColumnEncryptionProperties; | ||
| use crate::config::ConfigFileEncryptionProperties; | ||
| use parquet::encryption::encrypt::FileEncryptionProperties; | ||
| use std::collections::HashMap; | ||
|
|
||
| let valid_footer_key_as_hex = hex::encode(b"0123456789012345"); | ||
|
|
||
| let mut enc = ConfigFileEncryptionProperties { | ||
| encrypt_footer: true, | ||
| footer_key_as_hex: valid_footer_key_as_hex.clone(), | ||
| footer_key_metadata_as_hex: String::new(), | ||
| column_encryption_properties: HashMap::new(), | ||
| aad_prefix_as_hex: String::new(), | ||
| store_aad_prefix: false, | ||
| }; | ||
|
|
||
| // Encryption: invalid footer key hex | ||
| enc.footer_key_as_hex = "not_hex".to_string(); | ||
| let err = FileEncryptionProperties::try_from(enc.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Unable to decode hex footer key")); | ||
| enc.footer_key_as_hex = valid_footer_key_as_hex.clone(); | ||
|
|
||
| // Encryption: invalid footer key metadata hex | ||
| enc.footer_key_metadata_as_hex = "zz".to_string(); | ||
| let err = FileEncryptionProperties::try_from(enc.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Unable to decode hex footer key metadata")); | ||
| enc.footer_key_metadata_as_hex = String::new(); | ||
|
|
||
| // Encryption: invalid column key hex | ||
| enc.column_encryption_properties.insert( | ||
| "col1".to_string(), | ||
| ColumnEncryptionProperties { | ||
| column_key_as_hex: "bad".to_string(), | ||
| column_metadata_as_hex: None, | ||
| }, | ||
| ); | ||
| let err = FileEncryptionProperties::try_from(enc.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!( | ||
| err.contains("Unable to decode hex encryption key metadata for column col1") | ||
| ); | ||
| enc.column_encryption_properties.clear(); | ||
|
|
||
| // Encryption: invalid column metadata hex | ||
| enc.column_encryption_properties.insert( | ||
| "col1".to_string(), | ||
| ColumnEncryptionProperties { | ||
| column_key_as_hex: hex::encode(b"1234567890123450"), | ||
| column_metadata_as_hex: Some("zz".to_string()), | ||
| }, | ||
| ); | ||
| let err = FileEncryptionProperties::try_from(enc.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Unable to decode hex column metadata for column col1")); | ||
| enc.column_encryption_properties.clear(); | ||
|
|
||
| // Encryption: invalid AAD prefix hex | ||
| enc.aad_prefix_as_hex = "zz".to_string(); | ||
| let err = FileEncryptionProperties::try_from(enc.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Unable to decode hex AAD prefix")); | ||
| } | ||
|
|
||
| #[cfg(feature = "parquet_encryption")] | ||
| #[test] | ||
| fn parquet_encryption_invalid_hex_errors_decryption() { | ||
| use crate::config::ColumnDecryptionProperties; | ||
| use crate::config::ConfigFileDecryptionProperties; | ||
| use parquet::encryption::decrypt::FileDecryptionProperties; | ||
| use std::collections::HashMap; | ||
|
|
||
| let valid_footer_key_as_hex = hex::encode(b"0123456789012345"); | ||
|
|
||
| let mut dec = ConfigFileDecryptionProperties { | ||
| footer_key_as_hex: valid_footer_key_as_hex.clone(), | ||
| column_decryption_properties: HashMap::new(), | ||
| aad_prefix_as_hex: String::new(), | ||
| footer_signature_verification: true, | ||
| }; | ||
|
|
||
| // Decryption: invalid column key hex | ||
| dec.column_decryption_properties.insert( | ||
| "col1".to_string(), | ||
| ColumnDecryptionProperties { | ||
| column_key_as_hex: "bad".to_string(), | ||
| }, | ||
| ); | ||
| let err = FileDecryptionProperties::try_from(dec.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Could not decode hex column key")); | ||
| assert!(err.contains("col1")); | ||
| dec.column_decryption_properties.clear(); | ||
|
|
||
| // Decryption: invalid footer key hex | ||
| dec.footer_key_as_hex = "bad".to_string(); | ||
| let err = FileDecryptionProperties::try_from(dec.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Could not decode hex footer key")); | ||
| dec.footer_key_as_hex = valid_footer_key_as_hex; | ||
|
|
||
| // Decryption: invalid AAD prefix hex | ||
| dec.aad_prefix_as_hex = "zz".to_string(); | ||
| let err = FileDecryptionProperties::try_from(dec.clone()) | ||
| .unwrap_err() | ||
| .to_string(); | ||
| assert!(err.contains("Could not decode hex AAD prefix")); | ||
| } | ||
|
|
||
| #[cfg(feature = "parquet_encryption")] | ||
| #[test] | ||
| fn parquet_encryption_factory_config() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need entry in upgrade guide.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done @kumarUjjawal