ssh_vault/cli/actions/
edit.rs

1use crate::cli::actions::{Action, process_input};
2use crate::vault::{SshVault, crypto, dio, find, parse, ssh::decrypt_private_key};
3use anyhow::Result;
4use secrecy::{SecretSlice, SecretString};
5use std::io::{Read, Write};
6
7/// Handle the edit action
8/// # Errors
9/// Will return an error if the file cannot be read or written to
10pub fn handle(action: Action) -> Result<()> {
11    match action {
12        Action::Edit {
13            key,
14            vault,
15            passphrase,
16        } => {
17            let mut vault_data = String::new();
18
19            // set the R/W streams
20            let (mut input, mut output) = dio::setup_io(Some(vault.clone()), Some(vault))?;
21
22            // read the vault content
23            input.read_to_string(&mut vault_data)?;
24
25            // parse the vault
26            let (key_type, fingerprint, password, data) = parse(&vault_data)?;
27
28            // find the private_key using the vault header AES256 or CHACHA20-POLY1305
29            let mut private_key = find::private_key_type(key, key_type)?;
30
31            // decrypt private_key if encrypted
32            if private_key.is_encrypted() {
33                private_key = decrypt_private_key(&private_key, passphrase)?;
34            }
35
36            // RSA or ED25519
37            let key_type = find::key_type(&private_key.algorithm())?;
38
39            // initialize the vault
40            let vault = SshVault::new(&key_type, None, Some(private_key))?;
41
42            // decrypt the vault
43            let secret = vault.view(&password, &data, &fingerprint)?;
44
45            // store the new encrypted data
46            let mut new_secret = Vec::new();
47
48            // use the EDITOR env var to edit the existing secret
49            process_input(&mut new_secret, Some(SecretString::from(secret)))?;
50
51            // generate password (32 rand chars)
52            let password: SecretSlice<u8> = crypto::gen_password()?;
53
54            // create vault
55            let out = vault.create(password, &mut new_secret)?;
56
57            // save the vault
58            output.truncate()?;
59            output.write_all(out.as_bytes())?;
60        }
61        _ => unreachable!(),
62    }
63    Ok(())
64}