rightkit_agent_engine_api_integrations/
plugin_signature.rs1use serde::{Deserialize, Serialize};
4use std::path::{Path, PathBuf};
5
6#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
7#[serde(rename_all = "lowercase")]
8pub enum SignatureStatus {
9 Signed,
10 Unsigned,
11 Unknown,
12}
13
14#[derive(Clone, Debug, Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct PluginSignatureRecord {
17 pub status: SignatureStatus,
18 #[serde(default)]
19 pub signed_by: String,
20 #[serde(default)]
21 pub signing_public_key: String,
22 #[serde(default)]
23 pub signature: String,
24 #[serde(default)]
25 pub installed_at: String,
26 #[serde(default)]
27 pub install_source: String,
28}
29
30impl PluginSignatureRecord {
31 pub fn signed(
32 signed_by: String,
33 signing_public_key: String,
34 signature: String,
35 install_source: String,
36 now_iso: String,
37 ) -> Self {
38 Self {
39 status: SignatureStatus::Signed,
40 signed_by,
41 signing_public_key,
42 signature,
43 installed_at: now_iso,
44 install_source,
45 }
46 }
47
48 pub fn unsigned(install_source: String, now_iso: String) -> Self {
49 Self {
50 status: SignatureStatus::Unsigned,
51 signed_by: String::new(),
52 signing_public_key: String::new(),
53 signature: String::new(),
54 installed_at: now_iso,
55 install_source,
56 }
57 }
58}
59
60pub fn sidecar_path(plugin_install_dir: &Path) -> PathBuf {
61 plugin_install_dir.join(".signature.json")
62}
63
64pub fn read_record(plugin_install_dir: &Path) -> PluginSignatureRecord {
65 let path = sidecar_path(plugin_install_dir);
66 match std::fs::read_to_string(&path) {
67 Ok(raw) => serde_json::from_str(&raw).unwrap_or_else(|_| unknown_record()),
68 Err(_) => unknown_record(),
69 }
70}
71
72pub fn write_record(plugin_install_dir: &Path, record: &PluginSignatureRecord) {
73 let path = sidecar_path(plugin_install_dir);
74 match serde_json::to_string_pretty(record) {
75 Ok(json) => {
76 if let Err(error) = std::fs::write(&path, json) {
77 eprintln!(
78 "[plugin-signature] failed to write provenance to {}: {error}",
79 path.display()
80 );
81 }
82 }
83 Err(error) => eprintln!("[plugin-signature] serialise record failed: {error}"),
84 }
85}
86
87pub fn is_acceptable(record: &PluginSignatureRecord, policy_reject_unsigned: bool) -> bool {
88 match record.status {
89 SignatureStatus::Signed | SignatureStatus::Unknown => true,
90 SignatureStatus::Unsigned => !policy_reject_unsigned,
91 }
92}
93
94fn unknown_record() -> PluginSignatureRecord {
95 PluginSignatureRecord {
96 status: SignatureStatus::Unknown,
97 signed_by: String::new(),
98 signing_public_key: String::new(),
99 signature: String::new(),
100 installed_at: String::new(),
101 install_source: String::new(),
102 }
103}