1
use clap::Args;
2
use mk_lib::secrets::{
3
  load_secret_value,
4
  verify_vault,
5
};
6
use std::fs::File;
7
use std::io::Write as _;
8

            
9
use crate::secrets::context::Context;
10

            
11
#[derive(Debug, Args)]
12
pub struct ExportSecret {
13
  #[arg(help = "The secret identifier")]
14
  path: String,
15

            
16
  #[arg(short, long, help = "The output file")]
17
  output: Option<String>,
18

            
19
  #[arg(short, long, help = "The path to the secret vault")]
20
  vault_location: Option<String>,
21

            
22
  #[arg(long, help = "The keys location")]
23
  keys_location: Option<String>,
24

            
25
  #[arg(short, long, help = "The key name", conflicts_with = "gpg_key_id")]
26
  key_name: Option<String>,
27

            
28
  #[arg(
29
    long,
30
    conflicts_with = "key_name",
31
    help = "GPG key ID or fingerprint for hardware/passphrase-protected keys. Cannot be combined with --key-name."
32
  )]
33
  gpg_key_id: Option<String>,
34
}
35

            
36
impl ExportSecret {
37
  pub fn execute(&self, context: &Context) -> anyhow::Result<()> {
38
    let path: &str = &self.path.clone();
39
    let mut cli_overrides = context.settings().clone();
40
    if let Some(vault_location) = &self.vault_location {
41
      cli_overrides.vault_location = Some(vault_location.clone());
42
    }
43
    if let Some(keys_location) = &self.keys_location {
44
      cli_overrides.keys_location = Some(keys_location.clone());
45
    }
46
    if let Some(key_name) = &self.key_name {
47
      cli_overrides.key_name = Some(key_name.clone());
48
    }
49
    if let Some(gpg_key_id) = &self.gpg_key_id {
50
      cli_overrides.gpg_key_id = Some(gpg_key_id.clone());
51
    }
52
    let secret_config = context.resolve_with_settings(&cli_overrides);
53

            
54
    assert!(!path.is_empty(), "Path or prefix must be provided");
55

            
56
    verify_vault(&secret_config.vault_location)?;
57

            
58
    let value = load_secret_value(path, &secret_config)?;
59

            
60
    if let Some(output) = &self.output {
61
      let mut output_file = File::create(output)?;
62
      write!(output_file, "{}", value)?;
63
      output_file.flush()?;
64
    } else {
65
      println!("{}", value);
66
    }
67

            
68
    Ok(())
69
  }
70
}