brooks_lib/verifying/original/
verify.rs1use crate::{
21 cdni::{
22 gmd::spec::TypedGenericMetadata,
23 original::spec::{SourceMetadata, TypedSourceMetadata},
24 },
25 verifying::verify::{
26 AnalysisResult, CdniVerificationKey, MetadataAnalysisContext, MetadataVerificationError,
27 Verifier,
28 },
29};
30use std::{
31 fmt::{Debug, Display},
32 net::SocketAddr,
33 str::FromStr,
34};
35
36#[derive(Debug, Clone, Default)]
37pub struct SourceVerificationKey {
38 pub sources: Vec<(Vec<SocketAddr>, SourceProtocol)>,
39}
40
41#[derive(Debug, Clone, Default)]
42pub enum SourceProtocol {
43 #[default]
44 Http11,
45}
46
47impl Display for SourceProtocol {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 SourceProtocol::Http11 => write!(f, "Http1/1"),
51 }
52 }
53}
54
55impl FromStr for SourceProtocol {
56 type Err = MetadataVerificationError;
57
58 fn from_str(s: &str) -> Result<Self, Self::Err> {
59 if s == "http/1.1" {
60 return Ok(SourceProtocol::Http11);
61 }
62 Err(MetadataVerificationError::JsonError(format!(
63 "{} is not a valid protocol for Source MI",
64 s
65 )))
66 }
67}
68
69fn analyze_source_metadata(
70 to_verify: TypedSourceMetadata<()>,
71 input: MetadataAnalysisContext,
72) -> AnalysisResult<MetadataAnalysisContext, MetadataVerificationError> {
73 let mut sources: Vec<(Vec<SocketAddr>, SourceProtocol)> = vec![];
74
75 for s in &to_verify.value.sources {
76 let typed_protocol: SourceProtocol = s.protocol.parse()?;
77
78 let mut typed_endpoints: Vec<SocketAddr> = vec![];
79 for ep in &s.endpoints {
80 typed_endpoints.push(ep.parse().map_err(|_| {
81 MetadataVerificationError::JsonError(format!(
82 "{ep} is not a valid IP/Port combination"
83 ))
84 })?);
85 }
86
87 sources.push((typed_endpoints, typed_protocol));
88 }
89
90 let res = TypedSourceMetadata {
91 tpe: TypedSourceMetadata::<()>::typed_cdni_metadata_name(),
92 value: SourceMetadata::<SourceVerificationKey> {
93 sources: to_verify.value.sources,
94 aug: SourceVerificationKey { sources },
95 },
96 };
97
98 Ok((input, CdniVerificationKey::Source(Box::new(res))))
99}
100#[derive(Debug)]
101pub struct SourceMetadataAnalyzer {}
102
103impl Verifier<MetadataAnalysisContext, MetadataVerificationError> for SourceMetadataAnalyzer {
104 fn analyze(
105 &self,
106 v: &TypedGenericMetadata<()>,
107 input: MetadataAnalysisContext,
108 ) -> AnalysisResult<MetadataAnalysisContext, MetadataVerificationError> {
109 let typed_source = serde_json::from_value::<TypedSourceMetadata<()>>(
110 serde_json::to_value(v)
111 .map_err(|e| MetadataVerificationError::JsonError(e.to_string()))?,
112 )
113 .map_err(|e| MetadataVerificationError::JsonError(e.to_string()))?;
114
115 analyze_source_metadata(typed_source, input)
116 }
117
118 fn type_name(&self, candidate: &str) -> bool {
119 candidate == TypedSourceMetadata::<()>::typed_cdni_metadata_name()
120 }
121}
122
123#[cfg(test)]
124mod test_verify_source_metadata {
125 use std::{assert_matches, path::Path};
126
127 use crate::{
128 cdni::original::spec::{SourceMetadata, TypedSourceMetadata},
129 tests::read_test_file,
130 verifying::{
131 original::verify::analyze_source_metadata,
132 verify::{CdniVerificationKey, MetadataAnalysisContext},
133 },
134 };
135
136 #[test]
137 fn test_verify_8006_example() {
138 let json = read_test_file(Path::new(
139 "./src/cdni/tests/source/modified-8006-example.json",
140 ));
141 let cop_metadata = serde_json::from_str::<TypedSourceMetadata<()>>(&json)
142 .expect("Could not parse JSON test file");
143 assert_eq!(
144 cop_metadata.tpe,
145 TypedSourceMetadata::<()>::typed_cdni_metadata_name()
146 );
147
148 let (_, result) = analyze_source_metadata(cop_metadata, MetadataAnalysisContext::default())
149 .expect("Could not verify valid CDNI Source Metadata");
150
151 let result = match result {
152 CdniVerificationKey::Source(source) => source,
153 _ => panic!("Incorrect CDNI Verification Key type returned by analyze_source_metadata"),
154 };
155
156 assert_matches!(
157 *result,
158 TypedSourceMetadata {
159 tpe: _,
160 value: SourceMetadata { sources, aug: _ }
161 }
162 if sources.len() == 2 &&
163 sources[0].endpoints.len() == 2 &&
164 sources[1].endpoints.len() == 1
165 )
166 }
167}