-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move all YAML declarations under the
file_format::yaml
module.
- Loading branch information
Showing
9 changed files
with
285 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
86 changes: 86 additions & 0 deletions
86
crates/lib/src/rops_file/format/yaml/decrypted_map_to_tree.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use indexmap::IndexMap; | ||
use serde_yaml::{Mapping as YamlMap, Value as YamlValue}; | ||
|
||
use crate::*; | ||
|
||
impl TryFrom<RopsFileMap<Decrypted, YamlFileFormat>> for RopsTree<Decrypted> { | ||
type Error = DecryptedMapToTreeError; | ||
|
||
fn try_from(rops_file_map: RopsFileMap<Decrypted, YamlFileFormat>) -> Result<Self, Self::Error> { | ||
return recursive_map_call(rops_file_map.into_inner_map()); | ||
|
||
fn recursive_map_call(yaml_map: YamlMap) -> Result<RopsTree<Decrypted>, DecryptedMapToTreeError> { | ||
let mut inner_map = IndexMap::default(); | ||
|
||
for (yaml_key, value_yaml) in yaml_map { | ||
inner_map.insert(validate_key(yaml_key)?, recursive_value_call(value_yaml)?); | ||
} | ||
|
||
return Ok(RopsTree::Map(inner_map)); | ||
|
||
fn validate_key(yaml_value: YamlValue) -> Result<String, DecryptedMapToTreeError> { | ||
match yaml_value { | ||
YamlValue::String(string) => Ok(string), | ||
other => Err(DecryptedMapToTreeError::NonStringKey( | ||
serde_yaml::to_string(&other).expect("yaml value not serializable"), | ||
)), | ||
} | ||
} | ||
} | ||
|
||
fn recursive_value_call(yaml_value: YamlValue) -> Result<RopsTree<Decrypted>, DecryptedMapToTreeError> { | ||
Ok(match yaml_value { | ||
// SOPS simply throws away tags, so do we for now. | ||
// It can, however, deserialize manually added tags to encrypted documents, | ||
// so we could in theory keep the tags somewhere without breaking SOPS compatability. | ||
YamlValue::Tagged(tagged) => recursive_value_call(tagged.value)?, | ||
YamlValue::Mapping(map) => recursive_map_call(map)?, | ||
YamlValue::Bool(boolean) => RopsTree::Leaf(RopsValue::Boolean(boolean)), | ||
YamlValue::String(string) => RopsTree::Leaf(RopsValue::String(string)), | ||
YamlValue::Number(number) => RopsTree::Leaf(match number.is_f64() { | ||
true => RopsValue::Float(number.as_f64().expect("number not a f64")), | ||
false => RopsValue::Integer( | ||
number | ||
.as_i64() | ||
.ok_or_else(|| DecryptedMapToTreeError::IntegerOutOfRange(number.as_u64().expect("number not an u64")))?, | ||
), | ||
}), | ||
YamlValue::Sequence(sequence) => { | ||
RopsTree::Sequence(sequence.into_iter().map(recursive_value_call).collect::<Result<Vec<_>, _>>()?) | ||
} | ||
YamlValue::Null => RopsTree::Null, | ||
}) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn transforms_decrypted_yaml_map() { | ||
assert_eq!( | ||
RopsTree::mock(), | ||
RopsFileMap::<Decrypted, YamlFileFormat>::mock().try_into().unwrap() | ||
) | ||
} | ||
|
||
#[test] | ||
fn dissallows_non_string_keys() { | ||
let file_map = RopsFileMap::from_inner_map(serde_yaml::from_str::<YamlMap>("123: 456").unwrap()); | ||
assert!(matches!( | ||
RopsTree::try_from(file_map).unwrap_err(), | ||
DecryptedMapToTreeError::NonStringKey(_) | ||
)) | ||
} | ||
|
||
#[test] | ||
fn dissallows_out_of_range_integers() { | ||
let file_map = RopsFileMap::from_inner_map(serde_yaml::from_str::<YamlMap>(&format!("invalid_integer: {}", u64::MAX)).unwrap()); | ||
assert!(matches!( | ||
RopsTree::try_from(file_map).unwrap_err(), | ||
DecryptedMapToTreeError::IntegerOutOfRange(_) | ||
)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
mod rops_file { | ||
use crate::*; | ||
|
||
impl<S: RopsFileState> MockFileFormatUtil<YamlFileFormat> for RopsFile<S, YamlFileFormat> | ||
where | ||
RopsFileMap<S, YamlFileFormat>: MockFileFormatUtil<YamlFileFormat>, | ||
{ | ||
fn mock_format_display() -> String { | ||
indoc::formatdoc! {" | ||
{} | ||
sops: | ||
{}", | ||
RopsFileMap::mock_format_display(), | ||
textwrap::indent(&RopsFileMetadata::mock_format_display()," ") | ||
} | ||
} | ||
} | ||
} | ||
|
||
mod map { | ||
use crate::*; | ||
|
||
impl MockFileFormatUtil<YamlFileFormat> for RopsFileMap<Decrypted, YamlFileFormat> { | ||
fn mock_format_display() -> String { | ||
indoc::indoc! {" | ||
hello: world! | ||
nested_map: | ||
null_key: null | ||
array: | ||
- string | ||
- nested_map_in_array: | ||
integer: 1234 | ||
- float: 1234.56789 | ||
booleans: | ||
- true | ||
- false" | ||
} | ||
.to_string() | ||
} | ||
} | ||
|
||
#[cfg(feature = "aes-gcm")] | ||
impl MockFileFormatUtil<YamlFileFormat> for RopsFileMap<Encrypted<AES256GCM>, YamlFileFormat> { | ||
fn mock_format_display() -> String { | ||
indoc::indoc! {" | ||
hello: ENC[AES256_GCM,data:3S1E9am/,iv:WUQoQTrRXw/tUgwpmSG69xWtd5dVMfe8qUly1VB8ucM=,tag:nQUDkuh0OR1cjR5hGC5jOw==,type:str] | ||
nested_map: | ||
null_key: null | ||
array: | ||
- ENC[AES256_GCM,data:ANbeNrGp,iv:PRWGCPdOttPr5dlzT9te7WWCZ90J7+CvfY1vp60aADM=,tag:PvSLx4pLT5zRKOU0df8Xlg==,type:str] | ||
- nested_map_in_array: | ||
integer: ENC[AES256_GCM,data:qTW5qw==,iv:ugMxvR8YPwDgn2MbBpDX0lpCqzJY3GerhbA5jEKUbwE=,tag:d8utfA76C4XPzJyDfgE4Pw==,type:int] | ||
- float: ENC[AES256_GCM,data:/MTg0fCennyN8g==,iv:+/8+Ljm+cls7BbDYZnlg6NVFkrkw4GkEfWU2aGW57qE=,tag:26uMp2JmVAckySIaL2BLCg==,type:float] | ||
booleans: | ||
- ENC[AES256_GCM,data:bCdz2A==,iv:8kD+h1jClyVHBj9o2WZuAkjk+uD6A2lgNpcGljpQEhk=,tag:u3/fktl5HfFrVLERVvLRGw==,type:bool] | ||
- ENC[AES256_GCM,data:SgBh7wY=,iv:0s9Q9pQWbsZm2yHsmFalCzX0IqNb6ZqeY6QQYCWc+qU=,tag:OZb76BWCKbDLbcil4c8fYA==,type:bool]" | ||
} | ||
.to_string() | ||
} | ||
} | ||
|
||
impl<S: RopsFileState> MockTestUtil for RopsFileMap<S, YamlFileFormat> | ||
where | ||
Self: MockFileFormatUtil<YamlFileFormat>, | ||
{ | ||
fn mock() -> Self { | ||
serde_yaml::from_str(&Self::mock_format_display()).expect("mock yaml string not serializable") | ||
} | ||
} | ||
} | ||
|
||
mod metadata { | ||
mod core { | ||
use crate::*; | ||
|
||
impl MockFileFormatUtil<YamlFileFormat> for RopsFileMetadata { | ||
fn mock_format_display() -> String { | ||
#[cfg(feature = "age")] | ||
{ | ||
let age_metadata_yaml_string = RopsFileAgeMetadata::mock_format_display(); | ||
let (first_line, remaining_lines) = age_metadata_yaml_string | ||
.split_once('\n') | ||
.expect("no newline delimeter in yaml age metadata"); | ||
indoc::formatdoc! {" | ||
age: | ||
- {} | ||
{}", | ||
first_line, | ||
textwrap::indent(remaining_lines, " ") | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "age")] | ||
mod age { | ||
use crate::*; | ||
|
||
impl MockFileFormatUtil<YamlFileFormat> for RopsFileAgeMetadata { | ||
fn mock_format_display() -> String { | ||
indoc::formatdoc! {" | ||
recipient: {} | ||
enc: | | ||
{}", | ||
AgeIntegration::mock_public_key_str(), | ||
textwrap::indent(AgeIntegration::mock_encrypted_data_key_str()," ") | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use crate::*; | ||
|
||
#[derive(Debug, PartialEq)] | ||
pub struct YamlFileFormat; | ||
|
||
impl FileFormat for YamlFileFormat { | ||
type Map = serde_yaml::Mapping; | ||
type SerializeError = serde_yaml::Error; | ||
type DeserializeError = serde_yaml::Error; | ||
|
||
fn serialize_to_string<T: serde::Serialize>(t: &T) -> Result<String, Self::SerializeError> { | ||
serde_yaml::to_string(t) | ||
} | ||
|
||
fn deserialize_from_str<T: serde::de::DeserializeOwned>(str: &str) -> Result<T, Self::DeserializeError> { | ||
serde_yaml::from_str(str) | ||
} | ||
} | ||
|
||
mod encrypted_map_to_tree {} | ||
|
||
mod decrypted_map_to_tree; | ||
|
||
#[cfg(feature = "test-utils")] | ||
mod mock; | ||
|
||
#[cfg(test)] | ||
mod tests; |
Oops, something went wrong.