1use actix::prelude::*;
17use async_trait::async_trait;
18use futures_util::FutureExt;
19use reqwest::StatusCode;
20use serde::{Deserialize, Serialize};
21use std::collections::HashMap;
22use std::sync::Arc;
23use std::time::{Duration, SystemTime};
24use tokio::sync::broadcast;
25use tokio::time;
26use tracing::{debug, error, info, warn};
27
28use crate::database::{DatabaseManager, VaultCredentials};
29use crate::interface::VaultInterface;
30use crate::vault::common::VaultStatus;
31use crate::vault::init::{InitResult, UnsealResult};
32use crate::vault::setup_root::{setup_root_vault, RootSetupConfig};
33use crate::vault::setup_sub::{setup_sub_vault, SubSetupConfig, SubSetupResult};
34use crate::vault::{AutoUnsealResult, PkiResult, VaultError};
35
36#[derive(Debug, thiserror::Error)]
38pub enum ActorError {
39 #[error("Vault API error: {0}")]
40 VaultApi(String),
41
42 #[error("Network error: {0}")]
43 Network(String),
44
45 #[error("Actor operation failed: {0}")]
46 Operation(String),
47
48 #[error("Actor message handling failed: {0}")]
49 Messaging(String),
50
51 #[error("Timeout: {0}")]
52 Timeout(String),
53
54 #[error("HTTP error: {0}")]
55 HttpError(String),
56}
57
58impl From<VaultError> for ActorError {
60 fn from(error: VaultError) -> Self {
61 match error {
62 VaultError::Api(msg) => ActorError::VaultApi(msg),
63 VaultError::ApiError(msg) => ActorError::VaultApi(msg),
64 VaultError::Network(msg) => ActorError::Network(msg),
65 VaultError::Connection(msg) => ActorError::Network(msg),
66 VaultError::ParseError(msg) => ActorError::VaultApi(format!("Parse error: {}", msg)),
67 VaultError::Parsing(msg) => ActorError::VaultApi(format!("Parsing error: {}", msg)),
68 VaultError::HttpStatus(code, msg) => {
69 ActorError::VaultApi(format!("HTTP {}: {}", code, msg))
70 }
71 VaultError::AlreadyInitialized => {
72 ActorError::VaultApi("Vault is already initialized".to_string())
73 }
74 VaultError::Sealed(msg) => ActorError::VaultApi(format!("Vault is sealed: {}", msg)),
75 VaultError::RequestError(msg) => ActorError::Network(format!("Request error: {}", msg)),
76 VaultError::Reqwest(err) => ActorError::Network(format!("Reqwest error: {}", err)),
77 VaultError::Json(err) => ActorError::VaultApi(format!("JSON error: {}", err)),
78 }
79 }
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct VaultHealth {
84 pub addr: String,
85 pub initialized: bool,
86 pub sealed: bool,
87 pub standby: bool,
88 pub last_check: SystemTime,
89 pub is_auto_unsealed: bool,
90 pub unsealer_addr: Option<String>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub enum VaultEvent {
95 Initialized {
96 root_token: String,
97 keys: Vec<String>,
98 },
99 Unsealed {
100 progress: u8,
101 threshold: u8,
102 sealed: bool,
103 },
104 PkiSetupComplete {
105 role_name: String,
106 cert_chain: String,
107 },
108 AutounsealComplete {
109 root_token: String,
110 recovery_keys: Option<Vec<String>>,
111 },
112 StatusChecked {
113 initialized: bool,
114 sealed: bool,
115 standby: bool,
116 },
117 SetupComplete {
119 root_token: String,
120 root_role: String,
121 sub_token: String,
122 int_role: String,
123 },
124 Error(String),
125 VaultHealthUpdated {
126 addr: String,
127 health: VaultHealth,
128 },
129 VaultsListed {
130 vaults: Vec<VaultHealth>,
131 },
132 TransitTokenUnwrapped {
133 root_addr: String,
134 unwrapped_token: String,
135 },
136 TokenVerified {
137 valid: bool,
138 message: String,
139 },
140 TransitSetup {
141 success: bool,
142 key_name: String,
143 },
144 AutoUnsealDependencyError {
145 sub_addr: String,
146 root_addr: String,
147 error: String,
148 },
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct StatusInfo {
154 pub initialized: bool,
155 pub sealed: bool,
156 pub standby: bool,
157}
158
159impl From<VaultStatus> for StatusInfo {
160 fn from(status: VaultStatus) -> Self {
161 Self {
162 initialized: status.initialized,
163 sealed: status.sealed,
164 standby: status.standby,
165 }
166 }
167}
168
169#[derive(Clone)]
170pub struct VaultActor {
171 pub vault_addr: String,
172 pub root_token: Option<String>,
173 pub event_sender: Option<broadcast::Sender<VaultEvent>>,
174 pub known_vaults: HashMap<String, VaultHealth>,
175 pub unsealer_relationships: HashMap<String, String>,
176 pub db_manager: Option<Arc<DatabaseManager>>,
177}
178
179impl VaultActor {
180 pub fn new<S: Into<String>>(
181 vault_addr: S,
182 event_sender: Option<broadcast::Sender<VaultEvent>>,
183 ) -> Self {
184 Self {
185 vault_addr: vault_addr.into(),
186 root_token: None,
187 event_sender,
188 known_vaults: HashMap::new(),
189 unsealer_relationships: HashMap::new(),
190 db_manager: None,
191 }
192 }
193
194 pub fn new_with_test_config<S: Into<String>>(
196 vault_addr: S,
197 event_sender: Option<broadcast::Sender<VaultEvent>>,
198 ) -> Self {
199 Self {
200 vault_addr: vault_addr.into(),
201 root_token: None,
202 event_sender,
203 known_vaults: HashMap::new(),
204 unsealer_relationships: HashMap::new(),
205 db_manager: None,
206 }
207 }
208
209 pub fn with_database(mut self, db_manager: DatabaseManager) -> Self {
211 self.db_manager = Some(Arc::new(db_manager));
212
213 if self.root_token.is_none() && self.db_manager.is_some() {
215 if let Some(db) = &self.db_manager {
216 match db.load_vault_credentials() {
217 Ok(credentials) => {
218 if !credentials.root_token.is_empty() {
219 info!(
220 "Loaded root token from database for vault {}",
221 self.vault_addr
222 );
223 self.root_token = Some(credentials.root_token);
224 } else {
225 warn!(
226 "Root token in database is empty for vault {}",
227 self.vault_addr
228 );
229 }
230 }
231 Err(e) => {
232 warn!("Failed to load credentials from database: {}", e);
233 }
234 }
235 }
236 }
237
238 if let Some(db) = &self.db_manager {
240 match db.load_unsealer_relationships() {
241 Ok(relationships) => {
242 info!(
243 "Loaded {} unsealer relationships from database",
244 relationships.len()
245 );
246 self.unsealer_relationships = relationships;
247 }
248 Err(e) => {
249 warn!("Failed to load unsealer relationships from database: {}", e);
250 }
251 }
252 }
253
254 self
255 }
256
257 pub async fn start_monitoring(&mut self) {
258 let mut interval = time::interval(Duration::from_secs(30));
259
260 self.register_vault(self.vault_addr.clone()).await;
262
263 loop {
265 interval.tick().await;
266
267 let addrs: Vec<String> = self.known_vaults.keys().cloned().collect();
269 for addr in addrs {
270 self.register_vault(addr).await;
271 }
272
273 self.check_auto_unseal_dependencies().await;
275 }
276 }
277
278 async fn check_auto_unseal_dependencies(&mut self) {
280 debug!("Checking auto-unseal dependencies. Current state:");
282 debug!(
283 "Known vaults: {:?}",
284 self.known_vaults.keys().collect::<Vec<_>>()
285 );
286 debug!("Unsealer relationships: {:?}", self.unsealer_relationships);
287
288 for (sub_addr, root_addr) in self.unsealer_relationships.clone() {
290 if let Ok(root_status) = self.check_status(&root_addr).await {
292 if let Ok(sub_status) = self.check_status(&sub_addr).await {
293 let mut root_health = self
295 .known_vaults
296 .get(&root_addr)
297 .cloned()
298 .unwrap_or_else(|| VaultHealth {
299 addr: root_addr.clone(),
300 initialized: root_status.initialized,
301 sealed: root_status.sealed,
302 standby: root_status.standby,
303 last_check: SystemTime::now(),
304 is_auto_unsealed: false,
305 unsealer_addr: None,
306 });
307
308 root_health.initialized = root_status.initialized;
310 root_health.sealed = root_status.sealed;
311 root_health.standby = root_status.standby;
312 root_health.last_check = SystemTime::now();
313
314 let mut sub_health =
316 self.known_vaults
317 .get(&sub_addr)
318 .cloned()
319 .unwrap_or_else(|| VaultHealth {
320 addr: sub_addr.clone(),
321 initialized: sub_status.initialized,
322 sealed: sub_status.sealed,
323 standby: sub_status.standby,
324 last_check: SystemTime::now(),
325 is_auto_unsealed: true,
326 unsealer_addr: Some(root_addr.clone()),
327 });
328
329 sub_health.initialized = sub_status.initialized;
331 sub_health.sealed = sub_status.sealed;
332 sub_health.standby = sub_status.standby;
333 sub_health.last_check = SystemTime::now();
334
335 self.known_vaults
337 .insert(root_addr.clone(), root_health.clone());
338 self.known_vaults
339 .insert(sub_addr.clone(), sub_health.clone());
340
341 debug!(
343 "Checking auto-unseal dependency: root={} (sealed={}, init={}), sub={} (sealed={}, init={})",
344 root_addr, root_health.sealed, root_health.initialized,
345 sub_addr, sub_health.sealed, sub_health.initialized
346 );
347
348 if root_health.sealed || !root_health.initialized {
350 let error_msg = if root_health.sealed {
351 format!(
352 "Sub vault at {} cannot auto-unseal because root vault at {} is sealed",
353 sub_addr, root_addr
354 )
355 } else if !root_health.initialized {
356 format!("Sub vault at {} cannot auto-unseal because root vault at {} is not initialized", sub_addr, root_addr)
357 } else {
358 format!(
359 "Sub vault at {} cannot auto-unseal due to issues with root vault at {}",
360 sub_addr, root_addr
361 )
362 };
363
364 debug!("Auto-unseal dependency error detected: {}", error_msg);
365
366 if let Some(sender) = &self.event_sender {
368 debug!(
369 "Sending AutoUnsealDependencyError event for sub={}, root={}",
370 sub_addr, root_addr
371 );
372 let send_result = sender.send(VaultEvent::AutoUnsealDependencyError {
373 sub_addr: sub_addr.clone(),
374 root_addr: root_addr.clone(),
375 error: error_msg.clone(),
376 });
377
378 if let Err(e) = &send_result {
379 debug!("Failed to send AutoUnsealDependencyError event: {}", e);
380 } else {
381 debug!("Successfully sent AutoUnsealDependencyError event");
382 }
383
384 let general_result = sender.send(VaultEvent::Error(error_msg));
386 if let Err(e) = &general_result {
387 debug!("Failed to send Error event: {}", e);
388 }
389 } else {
390 warn!(
391 "No event sender available to send AutoUnsealDependencyError event"
392 );
393 }
394 } else {
395 debug!(
396 "No dependency issues detected between root={} and sub={}",
397 root_addr, sub_addr
398 );
399 }
400 } else {
401 warn!("Failed to check status for sub vault at {}", sub_addr);
402 }
403 } else {
404 warn!("Failed to check status for root vault at {}", root_addr);
405 }
406 }
407 }
408
409 async fn register_vault(&mut self, addr: String) {
410 let should_check_config = !self.known_vaults.contains_key(&addr);
411
412 if let Ok(status) = self.check_status(&addr).await {
413 let is_auto_unsealed = should_check_config && self.check_is_auto_unsealed(&addr).await;
415 let unsealer_addr = if is_auto_unsealed {
416 let root_addr = self.get_unsealer_address(&addr).await;
417 if let Some(root) = &root_addr {
418 self.unsealer_relationships
420 .insert(addr.clone(), root.clone());
421 }
422 root_addr
423 } else {
424 None
425 };
426
427 let health = VaultHealth {
428 addr: addr.clone(),
429 initialized: status.initialized,
430 sealed: status.sealed,
431 standby: status.standby,
432 last_check: SystemTime::now(),
433 is_auto_unsealed,
434 unsealer_addr,
435 };
436
437 self.known_vaults.insert(addr.clone(), health.clone());
439
440 if let Some(sender) = &self.event_sender {
442 let _ = sender.send(VaultEvent::VaultHealthUpdated {
443 addr: addr.clone(),
444 health,
445 });
446 }
447 }
448 }
449
450 async fn check_is_auto_unsealed(&self, addr: &str) -> bool {
452 let client = reqwest::Client::new();
454 let url = format!("{}/v1/sys/seal-status", addr);
455
456 if let Ok(resp) = client.get(&url).send().await {
457 if resp.status().is_success() {
458 if let Ok(json) = resp.json::<serde_json::Value>().await {
460 if let Some(seal_type) = json.get("type") {
461 return seal_type.as_str().unwrap_or("").contains("transit");
463 }
464 }
465 }
466 }
467
468 false
469 }
470
471 async fn get_unsealer_address(&self, addr: &str) -> Option<String> {
473 let client = reqwest::Client::new();
475 let url = format!("{}/v1/sys/config/state/sanitized", addr);
476
477 if let Ok(resp) = client.get(&url).send().await {
483 if resp.status().is_success() {
484 if let Ok(json) = resp.json::<serde_json::Value>().await {
485 if let Some(seal) = json.get("seal") {
486 if let Some(config) = seal.get("config") {
487 if let Some(address) = config.get("address") {
488 return address.as_str().map(|s| s.to_string());
489 }
490 }
491 }
492 }
493 }
494 }
495
496 None
499 }
500
501 pub async fn check_dependencies_now(&mut self) {
503 let addrs: Vec<String> = self.known_vaults.keys().cloned().collect();
505 for addr in addrs {
506 self.register_vault(addr).await;
507 }
508
509 self.check_auto_unseal_dependencies().await;
511 }
512
513 pub async fn verify_token(&self, token: &str) -> Result<bool, VaultError> {
515 let client = reqwest::Client::new();
516 let url = format!("{}/v1/auth/token/lookup-self", self.vault_addr);
517
518 let response = client
519 .get(&url)
520 .header("X-Vault-Token", token)
521 .send()
522 .await
523 .map_err(|e| VaultError::Network(format!("Network error: {}", e)))?;
524
525 if response.status().is_success() {
527 return Ok(true);
528 }
529
530 Ok(false)
532 }
533}
534
535impl Actor for VaultActor {
536 type Context = Context<Self>;
537}
538
539#[async_trait]
541pub trait VaultOperations {
542 async fn initialize(
544 &mut self,
545 secret_shares: u8,
546 secret_threshold: u8,
547 ) -> Result<InitResult, VaultError>;
548
549 async fn unseal(&mut self, keys: Vec<String>) -> Result<UnsealResult, VaultError>;
551
552 async fn status(&self) -> Result<VaultStatus, VaultError>;
554
555 async fn setup_pki(&mut self, role_name: String) -> Result<PkiResult, VaultError>;
557
558 async fn auto_unseal(
560 &mut self,
561 recovery_shares: Option<u8>,
562 ) -> Result<AutoUnsealResult, VaultError>;
563
564 }
566
567#[async_trait]
568impl VaultOperations for VaultActor {
569 async fn initialize(
570 &mut self,
571 secret_shares: u8,
572 secret_threshold: u8,
573 ) -> Result<InitResult, VaultError> {
574 let addr = self.vault_addr.clone();
575 let event_sender = self.event_sender.clone();
576
577 match crate::vault::init::init_vault(&addr, secret_shares, secret_threshold, None, None)
578 .await
579 {
580 Ok(init_resp) => {
581 if let Some(sender) = &event_sender {
582 let _ = sender.send(VaultEvent::Initialized {
583 root_token: init_resp.root_token.clone(),
584 keys: init_resp.keys.clone(),
585 });
586 }
587 self.root_token = Some(init_resp.root_token.clone());
588 Ok(init_resp)
589 }
590 Err(err) => {
591 if let Some(sender) = &event_sender {
592 let _ = sender.send(VaultEvent::Error(format!("{}", err)));
593 }
594 Err(VaultError::Api(format!("Initialization error: {}", err)))
595 }
596 }
597 }
598
599 async fn unseal(&mut self, keys: Vec<String>) -> Result<UnsealResult, VaultError> {
600 let addr = self.vault_addr.clone();
601 let event_sender = self.event_sender.clone();
602
603 match crate::vault::init::unseal_root_vault(&addr, keys).await {
604 Ok(unseal_resp) => {
605 if let Some(sender) = &event_sender {
606 let _ = sender.send(VaultEvent::Unsealed {
607 progress: unseal_resp.progress,
608 threshold: unseal_resp.threshold,
609 sealed: unseal_resp.sealed,
610 });
611 }
612 Ok(unseal_resp)
613 }
614 Err(err) => {
615 if let Some(sender) = &event_sender {
616 let _ = sender.send(VaultEvent::Error(format!("{}", err)));
617 }
618 Err(VaultError::Api(format!("Unseal error: {}", err)))
619 }
620 }
621 }
622
623 async fn status(&self) -> Result<VaultStatus, VaultError> {
624 let addr = self.vault_addr.clone();
625 let event_sender = self.event_sender.clone();
626
627 match crate::vault::common::check_vault_status(&addr).await {
628 Ok(status) => {
629 if let Some(sender) = &event_sender {
630 let _ = sender.send(VaultEvent::StatusChecked {
631 initialized: status.initialized,
632 sealed: status.sealed,
633 standby: status.standby,
634 });
635 }
636 Ok(status)
637 }
638 Err(err) => {
639 if let Some(sender) = &event_sender {
640 let _ = sender.send(VaultEvent::Error(format!("{}", err)));
641 }
642 Err(VaultError::Api(format!("Status check error: {}", err)))
643 }
644 }
645 }
646
647 async fn setup_pki(&mut self, role_name: String) -> Result<PkiResult, VaultError> {
648 let addr = self.vault_addr.clone();
649 let event_sender = self.event_sender.clone();
650 let token = self.root_token.clone().unwrap_or_default();
651
652 let common_name = role_name.clone();
654 let ttl = "8760h";
655 let intermediate = false;
656 let intermediate_addr = None;
657 let int_token = None;
658
659 match crate::vault::pki::setup_pki(
660 &addr,
661 &token,
662 &common_name,
663 ttl,
664 intermediate,
665 intermediate_addr,
666 int_token,
667 )
668 .await
669 {
670 Ok((cert_chain, role)) => {
671 let result = PkiResult {
672 cert_chain,
673 role_name: role,
674 };
675
676 if let Some(sender) = &event_sender {
677 let _ = sender.send(VaultEvent::PkiSetupComplete {
678 role_name: result.role_name.clone(),
679 cert_chain: result.cert_chain.clone(),
680 });
681 }
682 Ok(result)
683 }
684 Err(err) => {
685 if let Some(sender) = &event_sender {
686 let _ = sender.send(VaultEvent::Error(format!("{}", err)));
687 }
688 Err(VaultError::Api(format!("PKI setup error: {}", err)))
689 }
690 }
691 }
692
693 async fn auto_unseal(
694 &mut self,
695 _recovery_shares: Option<u8>,
696 ) -> Result<AutoUnsealResult, VaultError> {
697 let addr = self.vault_addr.clone();
698 let event_sender = self.event_sender.clone();
699
700 match crate::vault::autounseal::init_with_autounseal(&addr).await {
701 Ok(init_result) => {
702 let auto_result = AutoUnsealResult {
703 root_token: init_result.root_token.clone(),
704 recovery_keys: init_result.recovery_keys.clone(),
705 success: true,
706 };
707
708 if let Some(sender) = &event_sender {
709 let _ = sender.send(VaultEvent::AutounsealComplete {
710 root_token: auto_result.root_token.clone(),
711 recovery_keys: auto_result.recovery_keys.clone(),
712 });
713 }
714
715 self.root_token = Some(init_result.root_token);
717 Ok(auto_result)
718 }
719 Err(err) => {
720 if let Some(sender) = &event_sender {
721 let _ = sender.send(VaultEvent::Error(format!("{}", err)));
722 }
723 Err(VaultError::Api(format!("Auto-unseal error: {}", err)))
724 }
725 }
726 }
727}
728
729#[derive(Message, Debug, Clone)]
735#[rtype(result = "Result<InitResult, ActorError>")]
736pub struct InitVault {
737 pub secret_shares: u8,
738 pub secret_threshold: u8,
739}
740
741impl Handler<InitVault> for VaultActor {
742 type Result = ResponseFuture<Result<InitResult, ActorError>>;
743
744 fn handle(&mut self, msg: InitVault, _ctx: &mut Context<Self>) -> Self::Result {
745 let mut actor = self.clone();
746 async move {
747 actor
748 .initialize(msg.secret_shares, msg.secret_threshold)
749 .await
750 .map_err(ActorError::from)
751 }
752 .boxed_local()
753 }
754}
755
756#[derive(Message, Debug, Clone)]
758#[rtype(result = "Result<UnsealResult, ActorError>")]
759pub struct UnsealVault {
760 pub keys: Vec<String>,
761}
762
763impl Handler<UnsealVault> for VaultActor {
764 type Result = ResponseFuture<Result<UnsealResult, ActorError>>;
765
766 fn handle(&mut self, msg: UnsealVault, _ctx: &mut Context<Self>) -> Self::Result {
767 let actor = self.clone();
768 let addr = actor.vault_addr.clone();
769 async move {
770 actor
771 .unseal(&addr, msg.keys)
772 .await
773 .map_err(ActorError::from)
774 }
775 .boxed_local()
776 }
777}
778
779#[derive(Message, Debug, Clone)]
781#[rtype(result = "Result<StatusInfo, ActorError>")]
782pub struct CheckStatus;
783
784impl Handler<CheckStatus> for VaultActor {
785 type Result = ResponseFuture<Result<StatusInfo, ActorError>>;
786
787 fn handle(&mut self, _: CheckStatus, _ctx: &mut Context<Self>) -> Self::Result {
788 let _addr = self.vault_addr.clone();
789 let actor = self.clone();
790 Box::pin(async move {
791 match actor.status().await {
792 Ok(status) => Ok(StatusInfo::from(status)),
793 Err(e) => Err(e.into()),
794 }
795 })
796 }
797}
798
799#[derive(Message, Debug, Clone)]
801#[rtype(result = "Result<PkiResult, ActorError>")]
802pub struct SetupPki {
803 pub role_name: String,
804}
805
806impl Handler<SetupPki> for VaultActor {
807 type Result = ResponseFuture<Result<PkiResult, ActorError>>;
808
809 fn handle(&mut self, msg: SetupPki, _ctx: &mut Context<Self>) -> Self::Result {
810 let mut actor = self.clone();
811 async move {
812 actor
813 .setup_pki(msg.role_name)
814 .await
815 .map_err(ActorError::from)
816 }
817 .boxed_local()
818 }
819}
820
821#[derive(Message, Debug, Clone)]
823#[rtype(result = "Result<AutoUnsealResult, ActorError>")]
824pub struct AutoUnseal;
825
826impl Handler<AutoUnseal> for VaultActor {
827 type Result = ResponseFuture<Result<AutoUnsealResult, ActorError>>;
828
829 fn handle(&mut self, _msg: AutoUnseal, _ctx: &mut Context<Self>) -> Self::Result {
830 let mut actor = self.clone();
831 async move { actor.auto_unseal(None).await.map_err(ActorError::from) }.boxed_local()
832 }
833}
834
835#[derive(Message, Debug, Clone)]
837#[rtype(result = "Result<String, ActorError>")]
838pub struct SetupRoot {
839 pub addr: String,
840 pub secret_shares: u8,
841 pub secret_threshold: u8,
842 pub key_name: String,
843}
844
845#[derive(Message, Debug, Clone)]
846#[rtype(result = "Result<String, ActorError>")]
847pub struct SetupSub {
848 pub root_addr: String,
849 pub root_token: String,
850 pub sub_addr: String,
851 pub domain: String,
852 pub ttl: String,
853}
854
855impl Handler<SetupRoot> for VaultActor {
856 type Result = ResponseFuture<Result<String, ActorError>>;
857
858 fn handle(&mut self, msg: SetupRoot, _ctx: &mut Context<Self>) -> Self::Result {
859 let mut actor = self.clone();
860 async move {
861 actor.register_vault(msg.addr.clone()).await;
863
864 let config = RootSetupConfig {
865 root_addr: msg.addr.clone(),
866 secret_shares: msg.secret_shares,
867 secret_threshold: msg.secret_threshold,
868 key_name: msg.key_name.clone(),
869 mode: "local".to_string(),
870 output_file: None,
871 };
872
873 match setup_root_vault(config).await {
874 Ok(result) => {
875 if let Some(sender) = &actor.event_sender {
877 let _ = sender.send(VaultEvent::Initialized {
878 root_token: result.root_init.root_token.clone(),
879 keys: result.root_init.keys.clone(),
880 });
881 }
882
883 Ok(result.unwrapped_token)
885 }
886 Err(e) => Err(ActorError::VaultApi(format!("Root setup error: {}", e))),
887 }
888 }
889 .boxed_local()
890 }
891}
892
893impl Handler<SetupSub> for VaultActor {
894 type Result = ResponseFuture<Result<String, ActorError>>;
895
896 fn handle(&mut self, msg: SetupSub, _ctx: &mut Context<Self>) -> Self::Result {
897 let mut actor = self.clone();
898 async move {
899 actor.register_vault(msg.root_addr.clone()).await;
901 actor.register_vault(msg.sub_addr.clone()).await;
902
903 actor
905 .unsealer_relationships
906 .insert(msg.sub_addr.clone(), msg.root_addr.clone());
907
908 let config = SubSetupConfig {
909 sub_addr: msg.sub_addr.clone(),
910 domain: msg.domain,
911 ttl: msg.ttl,
912 root_addr: msg.root_addr.clone(),
913 root_token: msg.root_token,
914 };
915
916 match setup_sub_vault(config).await {
917 Ok(SubSetupResult {
918 sub_init,
919 pki_roles,
920 }) => {
921 let int_role = pki_roles.1.clone();
922 if let Some(sender) = &actor.event_sender {
923 let _ = sender.send(VaultEvent::SetupComplete {
924 root_token: sub_init.root_token.clone(),
925 root_role: pki_roles.0.clone(),
926 sub_token: sub_init.root_token,
927 int_role: pki_roles.1.clone(),
928 });
929 }
930 Ok(int_role)
931 }
932 Err(e) => Err(ActorError::VaultApi(format!("Sub setup error: {}", e))),
933 }
934 }
935 .boxed_local()
936 }
937}
938
939#[derive(Message, Debug, Clone)]
941#[rtype(result = "Result<String, ActorError>")]
942pub struct GetUnwrappedTransitToken {
943 pub root_addr: String,
944 pub root_token: String,
945 pub key_name: String,
946}
947
948impl Handler<GetUnwrappedTransitToken> for VaultActor {
949 type Result = ResponseFuture<Result<String, ActorError>>;
950
951 fn handle(&mut self, msg: GetUnwrappedTransitToken, _ctx: &mut Context<Self>) -> Self::Result {
952 let actor = self.clone();
953 async move {
954 debug!(
955 "Getting unwrapped transit token from root vault at {}",
956 msg.root_addr
957 );
958
959 if let Err(e) = crate::vault::autounseal::setup_transit_autounseal(
961 &msg.root_addr,
962 &msg.root_token,
963 &msg.key_name,
964 )
965 .await
966 {
967 return Err(ActorError::VaultApi(format!(
968 "Failed to setup transit auto-unseal: {}",
969 e
970 )));
971 }
972
973 let wrap_ttl = "300s";
975 let wrapped_token = match crate::vault::transit::generate_wrapped_transit_token(
976 &msg.root_addr,
977 &msg.root_token,
978 "autounseal", wrap_ttl,
980 )
981 .await
982 {
983 Ok(token) => token,
984 Err(e) => {
985 return Err(ActorError::VaultApi(format!(
986 "Failed to generate wrapped token: {}",
987 e
988 )))
989 }
990 };
991
992 let unwrapped_token = match crate::vault::autounseal::unwrap_token(
994 &msg.root_addr,
995 &wrapped_token,
996 )
997 .await
998 {
999 Ok(token) => token,
1000 Err(e) => {
1001 return Err(ActorError::VaultApi(format!(
1002 "Failed to unwrap token: {}",
1003 e
1004 )))
1005 }
1006 };
1007
1008 debug!("Successfully obtained unwrapped transit token");
1009
1010 if let Some(sender) = &actor.event_sender {
1012 let _ = sender.send(VaultEvent::TransitTokenUnwrapped {
1013 root_addr: msg.root_addr,
1014 unwrapped_token: unwrapped_token.clone(),
1015 });
1016 }
1017
1018 Ok(unwrapped_token)
1019 }
1020 .boxed_local()
1021 }
1022}
1023
1024#[derive(Message, Debug, Clone)]
1028#[rtype(result = "Result<String, ActorError>")]
1029pub struct SetupTransit {
1030 pub token: String,
1031 pub key_name: String,
1032}
1033
1034impl Handler<SetupTransit> for VaultActor {
1035 type Result = ResponseFuture<Result<String, ActorError>>;
1036
1037 fn handle(&mut self, msg: SetupTransit, _ctx: &mut Context<Self>) -> Self::Result {
1038 let actor = self.clone();
1039 let addr = actor.vault_addr.clone();
1040
1041 async move {
1042 match crate::vault::autounseal::setup_transit_autounseal(
1043 &addr,
1044 &msg.token,
1045 &msg.key_name,
1046 )
1047 .await
1048 {
1049 Ok(_result) => {
1050 if let Some(sender) = &actor.event_sender {
1051 let _ = sender.send(VaultEvent::TransitSetup {
1052 success: true,
1053 key_name: msg.key_name.clone(),
1054 });
1055 }
1056 Ok(msg.key_name)
1057 }
1058 Err(e) => {
1059 if let Some(sender) = &actor.event_sender {
1060 let _ =
1061 sender.send(VaultEvent::Error(format!("Transit setup error: {}", e)));
1062 }
1063 Err(ActorError::from(e))
1064 }
1065 }
1066 }
1067 .boxed_local()
1068 }
1069}
1070
1071#[derive(Message, Debug, Clone)]
1073#[rtype(result = "Result<String, ActorError>")]
1074pub struct GenerateWrappedToken {
1075 pub policy_name: String,
1076 pub wrap_ttl: String,
1077 pub token: String,
1078}
1079
1080impl Handler<GenerateWrappedToken> for VaultActor {
1081 type Result = ResponseFuture<Result<String, ActorError>>;
1082
1083 fn handle(&mut self, msg: GenerateWrappedToken, _ctx: &mut Context<Self>) -> Self::Result {
1084 let actor = self.clone();
1085 let addr = actor.vault_addr.clone();
1086
1087 async move {
1088 match crate::vault::transit::generate_wrapped_transit_token(
1089 &addr,
1090 &msg.token,
1091 &msg.policy_name,
1092 &msg.wrap_ttl,
1093 )
1094 .await
1095 {
1096 Ok(wrapped_token) => Ok(wrapped_token),
1097 Err(e) => {
1098 if let Some(sender) = &actor.event_sender {
1099 let _ = sender.send(VaultEvent::Error(format!(
1100 "Wrapped token generation error: {}",
1101 e
1102 )));
1103 }
1104 Err(ActorError::from(e))
1105 }
1106 }
1107 }
1108 .boxed_local()
1109 }
1110}
1111
1112#[derive(Message, Debug, Clone)]
1114#[rtype(result = "Result<String, ActorError>")]
1115pub struct UnwrapToken {
1116 pub wrapped_token: String,
1117}
1118
1119impl Handler<UnwrapToken> for VaultActor {
1120 type Result = ResponseFuture<Result<String, ActorError>>;
1121
1122 fn handle(&mut self, msg: UnwrapToken, _ctx: &mut Context<Self>) -> Self::Result {
1123 let actor = self.clone();
1124 let addr = actor.vault_addr.clone();
1125
1126 async move {
1127 match crate::vault::autounseal::unwrap_token(&addr, &msg.wrapped_token).await {
1128 Ok(unwrapped_token) => {
1129 if let Some(sender) = &actor.event_sender {
1130 let _ = sender.send(VaultEvent::TransitTokenUnwrapped {
1131 root_addr: addr.clone(),
1132 unwrapped_token: unwrapped_token.clone(),
1133 });
1134 }
1135 Ok(unwrapped_token)
1136 }
1137 Err(e) => {
1138 if let Some(sender) = &actor.event_sender {
1139 let _ =
1140 sender.send(VaultEvent::Error(format!("Token unwrap error: {}", e)));
1141 }
1142 Err(ActorError::from(e))
1143 }
1144 }
1145 }
1146 .boxed_local()
1147 }
1148}
1149
1150#[derive(Message, Debug, Clone)]
1152#[rtype(result = "Result<bool, ActorError>")]
1153pub struct VerifyTokenPermissions {
1154 pub token: String,
1155 pub key_name: String,
1156}
1157
1158impl Handler<VerifyTokenPermissions> for VaultActor {
1159 type Result = ResponseFuture<Result<bool, ActorError>>;
1160
1161 fn handle(&mut self, msg: VerifyTokenPermissions, _: &mut Context<Self>) -> Self::Result {
1162 let actor = self.clone();
1163 let addr = actor.vault_addr.clone();
1164
1165 Box::pin(async move {
1166 if msg.key_name.is_empty() {
1168 match actor.verify_token(&msg.token).await {
1169 Ok(valid) => {
1170 if let Some(sender) = &actor.event_sender {
1171 let _ = sender.send(VaultEvent::TokenVerified {
1172 valid,
1173 message: if valid {
1174 "Token is valid".into()
1175 } else {
1176 "Token is invalid".into()
1177 },
1178 });
1179 }
1180 return Ok(valid);
1181 }
1182 Err(e) => {
1183 if let Some(sender) = &actor.event_sender {
1184 let _ = sender.send(VaultEvent::TokenVerified {
1185 valid: false,
1186 message: format!("Token verification failed: {}", e),
1187 });
1188 }
1189 return Err(ActorError::from(e));
1190 }
1191 }
1192 }
1193
1194 let client = reqwest::Client::new();
1197 let encrypt_resp = client
1198 .post(format!("{}/v1/transit/encrypt/{}", addr, msg.key_name))
1199 .header("X-Vault-Token", &msg.token)
1200 .json(&serde_json::json!({
1201 "plaintext": "dGVzdA==" }))
1203 .send()
1204 .await;
1205
1206 match encrypt_resp {
1207 Ok(resp) => {
1208 if resp.status().is_success() {
1209 if let Some(sender) = &actor.event_sender {
1211 let _ = sender.send(VaultEvent::TokenVerified {
1212 valid: true,
1213 message: "Token has transit permissions".into(),
1214 });
1215 }
1216 Ok(true)
1217 } else {
1218 let body = resp
1219 .text()
1220 .await
1221 .unwrap_or_else(|_| "Unknown error".to_string());
1222 if let Some(sender) = &actor.event_sender {
1223 let _ = sender.send(VaultEvent::TokenVerified {
1224 valid: false,
1225 message: format!("Token verification failed: {}", body),
1226 });
1227 }
1228 Err(ActorError::VaultApi(format!(
1229 "Token permission verification failed: {}",
1230 body
1231 )))
1232 }
1233 }
1234 Err(e) => {
1235 if let Some(sender) = &actor.event_sender {
1236 let _ = sender.send(VaultEvent::TokenVerified {
1237 valid: false,
1238 message: format!("Token verification failed: {}", e),
1239 });
1240 }
1241 Err(ActorError::Network(format!(
1242 "Token verification request failed: {}",
1243 e
1244 )))
1245 }
1246 }
1247 })
1248 }
1249}
1250
1251#[derive(Message, Debug, Clone)]
1253#[rtype(result = "Result<(), ActorError>")]
1254pub struct CheckDependencies;
1255
1256async fn check_vault_health(
1258 client: &reqwest::Client,
1259 addr: &str,
1260) -> Result<VaultHealth, ActorError> {
1261 let status_url = format!("{}/v1/sys/health", addr);
1262
1263 let response = client
1264 .get(&status_url)
1265 .send()
1266 .await
1267 .map_err(|e| ActorError::Network(format!("Failed to connect to {}: {}", addr, e)))?;
1268
1269 if !response.status().is_success() {
1270 return if response.status() == StatusCode::INTERNAL_SERVER_ERROR {
1271 let health_data: serde_json::Value = response.json().await.map_err(|e| {
1273 ActorError::VaultApi(format!("Could not parse vault health response: {}", e))
1274 })?;
1275
1276 let initialized = health_data
1278 .get("initialized")
1279 .and_then(|v| v.as_bool())
1280 .unwrap_or(false);
1281 let sealed = health_data
1282 .get("sealed")
1283 .and_then(|v| v.as_bool())
1284 .unwrap_or(true);
1285 let standby = health_data
1286 .get("standby")
1287 .and_then(|v| v.as_bool())
1288 .unwrap_or(false);
1289
1290 Ok(VaultHealth {
1291 addr: addr.to_string(),
1292 initialized,
1293 sealed,
1294 standby,
1295 last_check: std::time::SystemTime::now(),
1296 is_auto_unsealed: false, unsealer_addr: None,
1298 })
1299 } else {
1300 Err(ActorError::VaultApi(format!(
1301 "Vault health check failed with status code: {}",
1302 response.status()
1303 )))
1304 };
1305 }
1306
1307 let health_data: serde_json::Value = response.json().await.map_err(|e| {
1309 ActorError::VaultApi(format!("Could not parse vault health response: {}", e))
1310 })?;
1311
1312 let initialized = health_data
1314 .get("initialized")
1315 .and_then(|v| v.as_bool())
1316 .unwrap_or(false);
1317 let sealed = health_data
1318 .get("sealed")
1319 .and_then(|v| v.as_bool())
1320 .unwrap_or(true);
1321 let standby = health_data
1322 .get("standby")
1323 .and_then(|v| v.as_bool())
1324 .unwrap_or(false);
1325
1326 Ok(VaultHealth {
1327 addr: addr.to_string(),
1328 initialized,
1329 sealed,
1330 standby,
1331 last_check: std::time::SystemTime::now(),
1332 is_auto_unsealed: false, unsealer_addr: None,
1334 })
1335}
1336
1337async fn check_auto_unseal_dependencies(
1339 _client: &reqwest::Client,
1340 sub_addr: &str,
1341 sub_health: &VaultHealth,
1342 root_addr: &str,
1343 root_health: &VaultHealth,
1344 event_tx: &broadcast::Sender<VaultEvent>,
1345) -> Result<(), ActorError> {
1346 info!(
1348 "Checking auto-unseal dependency: sub_vault={} (sealed={}, init={}), root_vault={} (sealed={}, init={})",
1349 sub_addr, sub_health.sealed, sub_health.initialized,
1350 root_addr, root_health.sealed, root_health.initialized
1351 );
1352
1353 if root_health.sealed || !root_health.initialized {
1355 let error_msg = if root_health.sealed {
1357 format!(
1358 "Root vault at {} is sealed, which prevents auto-unsealing of the sub vault at {}",
1359 root_addr, sub_addr
1360 )
1361 } else {
1362 format!("Root vault at {} is not initialized, which prevents auto-unsealing of the sub vault at {}",
1363 root_addr, sub_addr)
1364 };
1365
1366 error!("Auto-unseal dependency issue detected: {}", error_msg);
1367
1368 if let Err(e) = event_tx.send(VaultEvent::AutoUnsealDependencyError {
1370 sub_addr: sub_addr.to_string(),
1371 root_addr: root_addr.to_string(),
1372 error: error_msg,
1373 }) {
1374 error!("Failed to send AutoUnsealDependencyError event: {}", e);
1375 }
1376 }
1377
1378 Ok(())
1379}
1380
1381impl Handler<CheckDependencies> for VaultActor {
1382 type Result = ResponseFuture<Result<(), ActorError>>;
1383
1384 fn handle(&mut self, _msg: CheckDependencies, _ctx: &mut Self::Context) -> Self::Result {
1385 let unsealer_relationships = self.unsealer_relationships.clone();
1386 let known_vaults = self.known_vaults.clone();
1387 let event_tx = self.event_sender.clone().unwrap();
1388 let client = reqwest::Client::new();
1389
1390 Box::pin(async move {
1391 info!("Checking auto-unseal dependencies...");
1392
1393 info!("Known vaults: {:?}", known_vaults);
1395 info!("Unsealer relationships: {:?}", unsealer_relationships);
1396
1397 for (sub_addr, root_addr) in &unsealer_relationships {
1399 let root_health = match check_vault_health(&client, root_addr).await {
1401 Ok(health) => {
1402 info!(
1403 "Root vault health at {}: sealed={}, initialized={}",
1404 root_addr, health.sealed, health.initialized
1405 );
1406 health
1407 }
1408 Err(e) => {
1409 error!("Root vault {} is unreachable: {}", root_addr, e);
1411 let error_msg = format!("Root vault is unreachable: {}", e);
1412
1413 if let Err(e) = event_tx.send(VaultEvent::AutoUnsealDependencyError {
1414 sub_addr: sub_addr.clone(),
1415 root_addr: root_addr.clone(),
1416 error: error_msg,
1417 }) {
1418 error!("Failed to send event: {}", e);
1419 }
1420
1421 continue;
1422 }
1423 };
1424
1425 if root_health.sealed || !root_health.initialized {
1427 let error_msg = if root_health.sealed {
1429 format!("Root vault {} is sealed", root_addr)
1430 } else {
1431 format!("Root vault {} is not initialized", root_addr)
1432 };
1433
1434 error!("Auto-unseal dependency issue detected: {}", error_msg);
1435
1436 if let Err(e) = event_tx.send(VaultEvent::AutoUnsealDependencyError {
1437 sub_addr: sub_addr.clone(),
1438 root_addr: root_addr.clone(),
1439 error: error_msg,
1440 }) {
1441 error!("Failed to send event: {}", e);
1442 }
1443
1444 continue;
1445 }
1446
1447 let sub_health = match check_vault_health(&client, sub_addr).await {
1449 Ok(health) => {
1450 info!(
1451 "Sub vault health at {}: sealed={}, initialized={}",
1452 sub_addr, health.sealed, health.initialized
1453 );
1454 health
1455 }
1456 Err(e) => {
1457 warn!("Sub vault {} is unreachable: {}", sub_addr, e);
1459 continue;
1460 }
1461 };
1462
1463 if let Err(e) = check_auto_unseal_dependencies(
1465 &client,
1466 sub_addr,
1467 &sub_health,
1468 root_addr,
1469 &root_health,
1470 &event_tx,
1471 )
1472 .await
1473 {
1474 error!("Failed to check auto-unseal dependencies: {}", e);
1475 }
1476 }
1477
1478 Ok(())
1479 })
1480 }
1481}
1482
1483#[derive(Message, Debug, Clone)]
1485#[rtype(result = "Result<String, ActorError>")]
1486pub struct GetCurrentAddress;
1487
1488impl Handler<GetCurrentAddress> for VaultActor {
1489 type Result = ResponseFuture<Result<String, ActorError>>;
1490
1491 fn handle(&mut self, _: GetCurrentAddress, _ctx: &mut Context<Self>) -> Self::Result {
1492 let addr = self.vault_addr.clone();
1493 async move { Ok(addr) }.boxed_local()
1494 }
1495}
1496
1497#[derive(Message, Debug, Clone)]
1499#[rtype(result = "Result<(), ActorError>")]
1500pub struct SetCurrentAddress(pub String);
1501
1502impl Handler<SetCurrentAddress> for VaultActor {
1503 type Result = ResponseFuture<Result<(), ActorError>>;
1504
1505 fn handle(&mut self, msg: SetCurrentAddress, _ctx: &mut Context<Self>) -> Self::Result {
1506 let new_addr = msg.0;
1507 info!("Setting current vault address to {}", new_addr);
1508 self.vault_addr = new_addr.clone();
1509
1510 if self.root_token.is_none() && self.db_manager.is_some() {
1512 if let Some(db) = &self.db_manager {
1513 match db.load_vault_credentials() {
1514 Ok(credentials) => {
1515 if !credentials.root_token.is_empty() {
1516 info!(
1517 "Loaded root token from database for vault {}",
1518 self.vault_addr
1519 );
1520 self.root_token = Some(credentials.root_token);
1521 }
1522 }
1523 Err(e) => {
1524 warn!("Failed to load credentials from database: {}", e);
1525 }
1526 }
1527 }
1528 }
1529
1530 Box::pin(async move { Ok(()) })
1531 }
1532}
1533
1534#[derive(Message, Debug, Clone)]
1536#[rtype(result = "Result<(), ActorError>")]
1537pub struct AddUnsealerRelationship {
1538 pub sub_addr: String,
1539 pub root_addr: String,
1540}
1541
1542impl Handler<AddUnsealerRelationship> for VaultActor {
1543 type Result = ResponseFuture<Result<(), ActorError>>;
1544
1545 fn handle(&mut self, msg: AddUnsealerRelationship, _ctx: &mut Context<Self>) -> Self::Result {
1546 self.unsealer_relationships
1548 .insert(msg.sub_addr.clone(), msg.root_addr.clone());
1549
1550 info!(
1552 "Added unsealer relationship: sub={}, root={}",
1553 msg.sub_addr, msg.root_addr
1554 );
1555
1556 let db_manager = self.db_manager.clone();
1558 let sub_addr = msg.sub_addr.clone();
1559 let root_addr = msg.root_addr.clone();
1560
1561 let mut actor = self.clone();
1563
1564 async move {
1565 if let Some(db) = db_manager {
1567 if let Err(e) = db.save_unsealer_relationship(&sub_addr, &root_addr) {
1568 warn!("Failed to save unsealer relationship to database: {}", e);
1569 }
1570 }
1571
1572 actor.register_vault(sub_addr.clone()).await;
1574 actor.register_vault(root_addr.clone()).await;
1575
1576 if let Ok(root_status) = actor.check_status(&root_addr).await {
1578 if root_status.sealed || !root_status.initialized {
1579 let error_msg = if root_status.sealed {
1580 format!(
1581 "Root vault is sealed - sub vault {} will not be able to auto-unseal",
1582 sub_addr
1583 )
1584 } else {
1585 format!(
1586 "Root vault is not initialized - sub vault {} will not be able to auto-unseal",
1587 sub_addr
1588 )
1589 };
1590 warn!("{}", error_msg);
1591
1592 if let Some(sender) = &actor.event_sender {
1594 let _ = sender.send(VaultEvent::Error(error_msg));
1595 }
1596 }
1597 }
1598
1599 Ok(())
1600 }
1601 .boxed_local()
1602 }
1603}
1604
1605#[derive(Message, Debug, Clone)]
1607#[rtype(result = "Result<(), ActorError>")]
1608pub struct RegisterVault(pub String);
1609
1610impl Handler<RegisterVault> for VaultActor {
1611 type Result = ResponseFuture<Result<(), ActorError>>;
1612
1613 fn handle(&mut self, msg: RegisterVault, _ctx: &mut Context<Self>) -> Self::Result {
1614 let addr = msg.0;
1616 let mut actor = self.clone();
1617
1618 async move {
1619 actor.register_vault(addr.clone()).await;
1621 info!("Registered vault: {}", addr);
1622 Ok(())
1623 }
1624 .boxed_local()
1625 }
1626}
1627
1628#[derive(Message)]
1630#[rtype(result = "Result<(), ActorError>")]
1631pub struct SealVault {
1632 pub token: String,
1633}
1634
1635impl Handler<SealVault> for VaultActor {
1636 type Result = ResponseFuture<Result<(), ActorError>>;
1637
1638 fn handle(&mut self, msg: SealVault, _ctx: &mut Self::Context) -> Self::Result {
1639 let address = self.vault_addr.clone();
1640 let token = msg.token.clone();
1641 let event_sender = self.event_sender.clone();
1642
1643 Box::pin(async move {
1644 info!("Sealing vault at {}", address);
1645
1646 match crate::vault::seal_vault(&address, &token).await {
1647 Ok(_) => {
1648 info!("Successfully sealed vault at {}", address);
1649
1650 if let Some(sender) = &event_sender {
1652 let _ = sender.send(VaultEvent::Error(format!(
1653 "Vault at {} was intentionally sealed",
1654 address
1655 )));
1656 }
1657
1658 Ok(())
1659 }
1660 Err(err) => {
1661 error!("Failed to seal vault: {}", err);
1662
1663 if let Some(sender) = &event_sender {
1664 let _ = sender.send(VaultEvent::Error(format!(
1665 "Failed to seal vault at {}: {}",
1666 address, err
1667 )));
1668 }
1669
1670 Err(ActorError::VaultApi(format!(
1671 "Failed to seal vault: {}",
1672 err
1673 )))
1674 }
1675 }
1676 })
1677 }
1678}
1679
1680#[derive(Message, Debug, Clone)]
1682#[rtype(result = "Result<(), ActorError>")]
1683pub struct SetRootToken(pub String);
1684
1685impl Handler<SetRootToken> for VaultActor {
1686 type Result = Result<(), ActorError>;
1687
1688 fn handle(&mut self, msg: SetRootToken, _ctx: &mut Context<Self>) -> Self::Result {
1689 debug!("Setting root token in VaultActor");
1690 self.root_token = Some(msg.0);
1691 Ok(())
1692 }
1693}
1694
1695pub struct SyncToken {
1697 pub addr: String,
1698 pub token: String,
1699}
1700
1701impl Message for SyncToken {
1702 type Result = Result<(), ActorError>;
1703}
1704
1705impl Handler<SyncToken> for VaultActor {
1706 type Result = ResponseFuture<Result<(), ActorError>>;
1707
1708 fn handle(&mut self, msg: SyncToken, _ctx: &mut Self::Context) -> Self::Result {
1709 if self.vault_addr == msg.addr {
1711 self.root_token = Some(msg.token.clone());
1712 }
1713
1714 let token = msg.token.clone();
1716 let db_manager = self.db_manager.clone();
1717
1718 Box::pin(async move {
1719 if let Some(db) = db_manager {
1720 let mut credentials = match db.load_vault_credentials() {
1722 Ok(creds) => {
1723 info!("Loaded existing credentials from database for token update");
1724 creds
1725 }
1726 Err(e) => {
1727 warn!("Failed to load credentials from database: {}. Creating new credentials.", e);
1728 VaultCredentials::default()
1729 }
1730 };
1731
1732 credentials.root_token = token;
1734 info!(
1735 "Updated root token in credentials (length: {})",
1736 credentials.root_token.len()
1737 );
1738
1739 if let Err(e) = db.save_vault_credentials(&credentials) {
1741 warn!("Failed to save root token to database: {}", e);
1742 return Err(ActorError::Operation(format!(
1743 "Failed to save root token: {}",
1744 e
1745 )));
1746 }
1747
1748 info!("Successfully saved root token to database");
1749 }
1750 Ok(())
1751 })
1752 }
1753}
1754
1755pub struct SyncTransitToken {
1756 pub addr: String,
1757 pub token: String,
1758}
1759
1760impl Message for SyncTransitToken {
1761 type Result = Result<(), ActorError>;
1762}
1763
1764impl Handler<SyncTransitToken> for VaultActor {
1765 type Result = ResponseFuture<Result<(), ActorError>>;
1766
1767 fn handle(&mut self, msg: SyncTransitToken, _ctx: &mut Self::Context) -> Self::Result {
1768 let token = msg.token.clone();
1771 let db_manager = self.db_manager.clone();
1772
1773 Box::pin(async move {
1774 if let Some(db) = db_manager {
1775 let mut credentials = match db.load_vault_credentials() {
1777 Ok(creds) => {
1778 info!("Loaded existing credentials from database for transit token update");
1779 creds
1780 }
1781 Err(e) => {
1782 warn!("Failed to load credentials from database: {}. Creating new credentials.", e);
1783 VaultCredentials::default()
1784 }
1785 };
1786
1787 credentials.transit_token = token;
1789 info!(
1790 "Updated transit token in credentials (length: {})",
1791 credentials.transit_token.len()
1792 );
1793
1794 if let Err(e) = db.save_vault_credentials(&credentials) {
1796 warn!("Failed to save transit token to database: {}", e);
1797 return Err(ActorError::Operation(format!(
1798 "Failed to save transit token: {}",
1799 e
1800 )));
1801 }
1802
1803 info!("Successfully saved transit token to database");
1804 }
1805 Ok(())
1806 })
1807 }
1808}
1809
1810pub struct SyncSubToken {
1812 pub addr: String,
1813 pub token: String,
1814}
1815
1816impl Message for SyncSubToken {
1817 type Result = Result<(), ActorError>;
1818}
1819
1820impl Handler<SyncSubToken> for VaultActor {
1821 type Result = ResponseFuture<Result<(), ActorError>>;
1822
1823 fn handle(&mut self, msg: SyncSubToken, _ctx: &mut Self::Context) -> Self::Result {
1824 let token = msg.token.clone();
1826 let db_manager = self.db_manager.clone();
1827
1828 Box::pin(async move {
1829 if let Some(db) = db_manager {
1830 let mut credentials = match db.load_vault_credentials() {
1832 Ok(creds) => {
1833 info!("Loaded existing credentials from database for sub token update");
1834 creds
1835 }
1836 Err(e) => {
1837 warn!("Failed to load credentials from database: {}. Creating new credentials.", e);
1838 VaultCredentials::default()
1839 }
1840 };
1841
1842 credentials.sub_token = token;
1844 info!(
1845 "Updated sub token in credentials (length: {})",
1846 credentials.sub_token.len()
1847 );
1848
1849 if let Err(e) = db.save_vault_credentials(&credentials) {
1851 warn!("Failed to save sub token to database: {}", e);
1852 return Err(ActorError::Operation(format!(
1853 "Failed to save sub token: {}",
1854 e
1855 )));
1856 }
1857
1858 info!("Successfully saved sub token to database");
1859 }
1860 Ok(())
1861 })
1862 }
1863}
1864
1865pub fn start_vault_actor_with_channel(
1870 vault_addr: &str,
1871) -> (Addr<VaultActor>, broadcast::Receiver<VaultEvent>) {
1872 let (tx, rx) = broadcast::channel(16);
1873 let actor = VaultActor::new(vault_addr, Some(tx));
1874
1875 let monitoring_actor = actor.clone();
1877 let addr = actor.start();
1878
1879 tokio::spawn(async move {
1881 let mut monitoring_actor = monitoring_actor;
1882 monitoring_actor.start_monitoring().await;
1883 });
1884
1885 (addr, rx)
1886}
1887
1888#[async_trait]
1889impl VaultInterface for VaultActor {
1890 async fn check_status(&self, addr: &str) -> Result<VaultStatus, VaultError> {
1891 match crate::vault::common::check_vault_status(addr).await {
1892 Ok(status) => {
1893 if let Some(sender) = &self.event_sender {
1894 let _ = sender.send(VaultEvent::StatusChecked {
1895 initialized: status.initialized,
1896 sealed: status.sealed,
1897 standby: status.standby,
1898 });
1899 }
1900 Ok(status)
1901 }
1902 Err(err) => Err(VaultError::Api(format!("Status check error: {}", err))),
1903 }
1904 }
1905
1906 async fn unseal(&self, addr: &str, keys: Vec<String>) -> Result<UnsealResult, VaultError> {
1907 match crate::vault::init::unseal_root_vault(addr, keys).await {
1908 Ok(unseal_resp) => {
1909 if let Some(sender) = &self.event_sender {
1910 let _ = sender.send(VaultEvent::Unsealed {
1911 progress: unseal_resp.progress,
1912 threshold: unseal_resp.threshold,
1913 sealed: unseal_resp.sealed,
1914 });
1915 }
1916 Ok(unseal_resp)
1917 }
1918 Err(err) => Err(VaultError::Api(format!("Unseal error: {}", err))),
1919 }
1920 }
1921
1922 async fn setup_root(
1923 &self,
1924 addr: &str,
1925 secret_shares: u8,
1926 secret_threshold: u8,
1927 key_name: &str,
1928 ) -> Result<String, VaultError> {
1929 let config = RootSetupConfig {
1930 root_addr: addr.to_string(),
1931 secret_shares,
1932 secret_threshold,
1933 key_name: key_name.to_string(),
1934 mode: "local".to_string(),
1935 output_file: None,
1936 };
1937
1938 match setup_root_vault(config).await {
1939 Ok(result) => {
1940 if let Some(sender) = &self.event_sender {
1941 let _ = sender.send(VaultEvent::Initialized {
1942 root_token: result.root_init.root_token.clone(),
1943 keys: result.root_init.keys.clone(),
1944 });
1945 }
1946 Ok(result.unwrapped_token)
1947 }
1948 Err(e) => Err(VaultError::Api(format!("Root setup error: {}", e))),
1949 }
1950 }
1951
1952 async fn setup_sub(
1953 &self,
1954 root_addr: &str,
1955 root_token: &str,
1956 sub_addr: &str,
1957 domain: &str,
1958 ttl: &str,
1959 ) -> Result<String, VaultError> {
1960 let config = SubSetupConfig {
1961 sub_addr: sub_addr.to_string(),
1962 domain: domain.to_string(),
1963 ttl: ttl.to_string(),
1964 root_addr: root_addr.to_string(),
1965 root_token: root_token.to_string(),
1966 };
1967
1968 match setup_sub_vault(config).await {
1969 Ok(SubSetupResult {
1970 sub_init,
1971 pki_roles,
1972 }) => {
1973 if let Some(sender) = &self.event_sender {
1974 let _ = sender.send(VaultEvent::SetupComplete {
1975 root_token: sub_init.root_token.clone(),
1976 root_role: pki_roles.0.clone(),
1977 sub_token: sub_init.root_token,
1978 int_role: pki_roles.1.clone(),
1979 });
1980 }
1981 Ok(pki_roles.1)
1982 }
1983 Err(e) => Err(VaultError::Api(format!("Sub setup error: {}", e))),
1984 }
1985 }
1986
1987 async fn get_unwrapped_transit_token(
1988 &self,
1989 root_addr: &str,
1990 root_token: &str,
1991 key_name: &str,
1992 ) -> Result<String, VaultError> {
1993 debug!(
1994 "Getting unwrapped transit token from root vault at {}",
1995 root_addr
1996 );
1997
1998 if let Err(e) =
2000 crate::vault::autounseal::setup_transit_autounseal(root_addr, root_token, key_name)
2001 .await
2002 {
2003 return Err(VaultError::Api(format!(
2004 "Failed to setup transit auto-unseal: {}",
2005 e
2006 )));
2007 }
2008
2009 let wrap_ttl = "300s";
2011 let wrapped_token = match crate::vault::transit::generate_wrapped_transit_token(
2012 root_addr,
2013 root_token,
2014 "autounseal", wrap_ttl,
2016 )
2017 .await
2018 {
2019 Ok(token) => token,
2020 Err(e) => {
2021 return Err(VaultError::Api(format!(
2022 "Failed to generate wrapped token: {}",
2023 e
2024 )))
2025 }
2026 };
2027
2028 let unwrapped_token =
2030 match crate::vault::autounseal::unwrap_token(root_addr, &wrapped_token).await {
2031 Ok(token) => token,
2032 Err(e) => return Err(VaultError::Api(format!("Failed to unwrap token: {}", e))),
2033 };
2034
2035 debug!("Successfully obtained unwrapped transit token");
2036
2037 if let Some(sender) = &self.event_sender {
2039 let _ = sender.send(VaultEvent::TransitTokenUnwrapped {
2040 root_addr: root_addr.to_string(),
2041 unwrapped_token: unwrapped_token.clone(),
2042 });
2043 }
2044
2045 Ok(unwrapped_token)
2046 }
2047}