diff --git a/src/cli.rs b/src/cli.rs index d6f963a..f6b1a26 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -25,6 +25,8 @@ pub enum SubCommand { Init, /// Add or update a secret Encrypt { + /// Environment, must be ASCII characters + environment: String, /// Key, must be all capital ASCII characters, digits, and underscores key: String, /// Value. If omitted, read from stdin @@ -32,6 +34,7 @@ pub enum SubCommand { }, /// Generate a new strong secret value, and add it to the repository Generate { + environment: String, /// Key, must be all capital ASCII characters, digits, and underscores key: String, }, diff --git a/src/config.rs b/src/config.rs index 5b57191..0fb24a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,7 +16,7 @@ use sodiumoxide::{ pub const SECRET_KEY_ENV: &str = "AMBER_SECRET"; /// Current version of the file format -const FILE_FORMAT_VERSION: u32 = 1; +const FILE_FORMAT_VERSION: u32 = 2; /// Raw version of [Config], the thing actually serialized/deserialized #[derive(Serialize, Deserialize, Debug)] @@ -37,6 +37,7 @@ struct ConfigRaw { #[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] struct SecretRaw { + environment: String, name: String, sha256: String, cipher: String, @@ -143,7 +144,7 @@ impl Config { } /// Encrypt a new value, replacing as necessary - pub fn encrypt(&mut self, key: String, value: &str) { + pub fn encrypt(&mut self, environment: String, key: String, value: &str) { let hash = sha256::hash(value.as_bytes()); if let Some(old_secret) = self.secrets.get(&key) { if old_secret.sha256 == hash { @@ -155,6 +156,7 @@ impl Config { } self.secrets.insert( + environment, key, Secret { cipher: sealedbox::seal(value.as_bytes(), &self.public_key), diff --git a/src/main.rs b/src/main.rs index e05064b..c3c2697 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,8 +33,8 @@ fn main() -> Result<()> { log::debug!("{:?}", cmd); match cmd.sub { cli::SubCommand::Init => init(cmd.opt), - cli::SubCommand::Encrypt { key, value } => encrypt(cmd.opt, key, value), - cli::SubCommand::Generate { key } => generate(cmd.opt, key), + cli::SubCommand::Encrypt { environment, key, value } => encrypt(cmd.opt, environment, key, value), + cli::SubCommand::Generate { environment, key } => generate(cmd.opt, environment, key), cli::SubCommand::Remove { key } => remove(cmd.opt, key), cli::SubCommand::Print { style } => print(cmd.opt, style), cli::SubCommand::Exec { cmd: cmd_, args } => exec(cmd.opt, cmd_, args), @@ -72,7 +72,7 @@ fn validate_key(key: &str) -> Result<()> { } } -fn encrypt(mut opt: cli::Opt, key: String, value: Option) -> Result<()> { +fn encrypt(mut opt: cli::Opt, environment: String, key: String, value: Option) -> Result<()> { validate_key(&key)?; let amber_yaml = opt.find_amber_yaml()?; let mut config = config::Config::load(amber_yaml)?; @@ -91,15 +91,15 @@ fn encrypt(mut opt: cli::Opt, key: String, value: Option) -> Result<()> }, Ok, )?; - config.encrypt(key, &value); + config.encrypt(environment, key, &value); config.save(amber_yaml) } -fn generate(opt: cli::Opt, key: String) -> Result<()> { +fn generate(opt: cli::Opt, environment: String, key: String) -> Result<()> { let value = sodiumoxide::randombytes::randombytes(16); let value = sodiumoxide::base64::encode(value, sodiumoxide::base64::Variant::UrlSafe); let msg = format!("Your new secret value is {}: {}", key, value); - let res = encrypt(opt, key, Some(value))?; + let res = encrypt(opt, environment, key, Some(value))?; println!("{}", &msg); Ok(res) }