rite_runtime/
artifact_resolver.rs1use crate::actions::ArtifactValue;
14use crate::executor::ExecutionError;
15use rite_model::ArtifactId;
16use rite_sdk::{KeyAlgorithm, KeyCheckValue, KeyId, PublicKeyDer};
17use std::collections::HashMap;
18use std::hash::BuildHasher;
19
20pub fn resolve_artifact_bytes<S: BuildHasher>(
36 artifacts: &HashMap<ArtifactId, ArtifactValue, S>,
37 artifact_id: &ArtifactId,
38 property: Option<&str>,
39) -> Result<Vec<u8>, ExecutionError> {
40 let artifact = artifacts.get(artifact_id).ok_or_else(|| {
41 ExecutionError::InvalidParams(format!("Artifact '{artifact_id}' not found"))
42 })?;
43
44 match (artifact, property) {
45 (
47 ArtifactValue::BackendKey {
48 public_key: Some(pub_key),
49 ..
50 },
51 Some("public"),
52 ) => Ok(pub_key.as_bytes().to_vec()),
53 (
54 ArtifactValue::BackendKey {
55 public_key: None, ..
56 },
57 Some("public"),
58 ) => {
59 let id = artifact_id.as_str();
60 Err(ExecutionError::InvalidParams(format!(
61 "Public key for '{id}' is not exportable from backend"
62 )))
63 }
64 (ArtifactValue::BackendKey { .. }, Some("private")) => {
65 let id = artifact_id.as_str();
66 Err(ExecutionError::InvalidParams(format!(
67 "Cannot access private key from backend-managed key '{id}'"
68 )))
69 }
70
71 (
74 ArtifactValue::BackendKey {
75 check_value: Some(kcv),
76 ..
77 },
78 Some("kcv"),
79 ) => Ok(kcv.as_bytes().to_vec()),
80 (
81 ArtifactValue::BackendKey {
82 check_value: None,
83 algorithm,
84 ..
85 },
86 Some("kcv"),
87 ) => {
88 let id = artifact_id.as_str();
89 Err(ExecutionError::InvalidParams(format!(
90 "'{id}' is a {algorithm} key, which is named by its public half \
91 rather than by a check value"
92 )))
93 }
94
95 (ArtifactValue::PublicKey(key), None) => Ok(key.as_bytes().to_vec()),
97
98 (ArtifactValue::WrappedKey(wrapped), None) => Ok(wrapped.data().to_vec()),
100
101 (ArtifactValue::Bytes(bytes), None) => Ok(bytes.clone()),
103 (ArtifactValue::Text(text), None) => Ok(text.as_bytes().to_vec()),
104
105 (ArtifactValue::Certificate(certificate), None) => Ok(certificate.as_bytes().to_vec()),
108
109 _ => Err(ExecutionError::InvalidParams(format!(
111 "Cannot extract bytes from artifact '{artifact_id}' with property '{property:?}'"
112 ))),
113 }
114}
115
116#[derive(Debug, Clone, Copy)]
121#[non_exhaustive]
122pub struct BackendKeyMeta<'a> {
123 pub backend_name: &'a str,
125 pub key_id: &'a KeyId,
127 pub algorithm: KeyAlgorithm,
129 pub public_key: Option<&'a PublicKeyDer>,
131 pub check_value: Option<&'a KeyCheckValue>,
136}
137
138pub fn resolve_backend_key<'a, S: BuildHasher>(
148 artifacts: &'a HashMap<ArtifactId, ArtifactValue, S>,
149 artifact_id: &ArtifactId,
150) -> Result<BackendKeyMeta<'a>, ExecutionError> {
151 let id = artifact_id.as_str();
152 let artifact = artifacts
153 .get(artifact_id)
154 .ok_or_else(|| ExecutionError::InvalidParams(format!("Artifact '{id}' not found")))?;
155
156 match artifact {
157 ArtifactValue::BackendKey {
158 backend_name,
159 key_id,
160 algorithm,
161 public_key,
162 check_value,
163 } => Ok(BackendKeyMeta {
164 backend_name: backend_name.as_str(),
165 key_id,
166 algorithm: *algorithm,
167 public_key: public_key.as_ref(),
168 check_value: check_value.as_ref(),
169 }),
170 _ => Err(ExecutionError::InvalidParams(format!(
171 "Artifact '{id}' is not a backend-managed key"
172 ))),
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_resolve_bytes() {
182 let mut artifacts = HashMap::new();
183 artifacts.insert(
184 ArtifactId::new("ksr"),
185 ArtifactValue::Bytes(b"test content".to_vec()),
186 );
187
188 let result = resolve_artifact_bytes(&artifacts, &ArtifactId::new("ksr"), None).unwrap();
189 assert_eq!(result, b"test content");
190 }
191
192 #[test]
193 fn test_resolve_text() {
194 let mut artifacts = HashMap::new();
195 artifacts.insert(
196 ArtifactId::new("usb_drive"),
197 ArtifactValue::Text("USB Drive".to_string()),
198 );
199
200 let result =
201 resolve_artifact_bytes(&artifacts, &ArtifactId::new("usb_drive"), None).unwrap();
202 assert_eq!(result, b"USB Drive");
203 }
204
205 #[test]
206 fn test_resolve_not_found() {
207 let artifacts: HashMap<ArtifactId, ArtifactValue> = HashMap::new();
208 let result = resolve_artifact_bytes(&artifacts, &ArtifactId::new("missing"), None);
209 assert!(result.is_err());
210 }
211}