Skip to content

Commit 2c26aec

Browse files
committed
add: re-ecnrypt vars after edit
1 parent 11be2ef commit 2c26aec

File tree

5 files changed

+100
-21
lines changed

5 files changed

+100
-21
lines changed

src/age_utils.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ pub fn mount(target: &str) -> Mount {
2323
}
2424
}
2525

26+
pub enum Variable {
27+
Secret { value: String },
28+
ClearText { value: String },
29+
}
30+
31+
impl Variable {
32+
pub fn to_string(&self) -> String {
33+
match &self {
34+
Variable::Secret { value } => value.to_string(),
35+
Variable::ClearText { value } => value.to_string(),
36+
}
37+
}
38+
}
39+
2640
impl<'a> WorkspaceApi<'a> {
2741
pub async fn read_age_identity(&self) -> Result<Identity, AnyError> {
2842
let workspace_key = id::random_suffix("tmp");
@@ -104,8 +118,8 @@ pub fn encrypt(plaintext: String, recipient: Recipient) -> Result<String, AnyErr
104118
pub fn decrypt(
105119
identity: &dyn age::Identity,
106120
env_vars: LinkedHashMap<String, String>,
107-
) -> Result<LinkedHashMap<String, String>, AnyError> {
108-
let mut ret = LinkedHashMap::<String, String>::new();
121+
) -> Result<LinkedHashMap<String, Variable>, AnyError> {
122+
let mut ret = LinkedHashMap::<String, Variable>::new();
109123
for (k, v) in env_vars.iter() {
110124
if v.starts_with(SECRET_HEADER) {
111125
let formatted = v.replace("|", "\n");
@@ -126,10 +140,17 @@ pub fn decrypt(
126140

127141
ret.insert(
128142
k.to_string(),
129-
std::str::from_utf8(&decrypted[..])?.to_string(),
143+
Variable::Secret {
144+
value: std::str::from_utf8(&decrypted[..])?.to_string(),
145+
},
130146
);
131147
} else {
132-
ret.insert(k.to_string(), v.to_string());
148+
ret.insert(
149+
k.to_string(),
150+
Variable::ClearText {
151+
value: v.to_string(),
152+
},
153+
);
133154
}
134155
}
135156
Ok(ret)

src/api/workspace.rs

+71-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use std::path::Path;
2-
1+
use age::x25519::Identity;
32
use bollard::{
43
network::ListNetworksOptions,
54
service::{ContainerSummary, Volume},
65
volume::ListVolumesOptions,
76
};
87
use linked_hash_map::LinkedHashMap;
8+
use std::path::Path;
99

1010
use crate::{
11-
age_utils,
11+
age_utils::{self, Variable},
1212
api::WorkspaceApi,
1313
constants,
1414
labels::{self, Labels, ROLE},
@@ -211,21 +211,61 @@ impl<'a> WorkspaceApi<'a> {
211211
Ok(())
212212
}
213213

214+
pub fn encrypt(
215+
&self,
216+
identity: Identity,
217+
name: &str,
218+
vars: LinkedHashMap<String, String>,
219+
) -> Result<LinkedHashMap<String, String>, AnyError> {
220+
let encrypted = self.encrypt_value(identity, vars[name].to_string())?;
221+
let mut new_vars = vars.clone();
222+
new_vars.insert(name.to_string(), encrypted);
223+
Ok(new_vars)
224+
}
225+
226+
pub fn encrypt_value(
227+
&self,
228+
identity: Identity,
229+
clear_text: String,
230+
) -> Result<String, AnyError> {
231+
age_utils::encrypt(clear_text, identity.to_public())
232+
}
233+
214234
pub async fn decrypt(
215235
&self,
216236
vars: Option<LinkedHashMap<String, String>>,
217-
) -> Result<LinkedHashMap<String, String>, AnyError> {
237+
) -> Result<LinkedHashMap<String, age_utils::Variable>, AnyError> {
218238
log::debug!("Checking if vars need decryption");
219239
if let Some(vars) = age_utils::needs_decryption(vars.clone()) {
220240
log::debug!("Decrypting vars");
221241
let identity = self.read_age_identity().await?;
222242
age_utils::decrypt(&identity, vars)
223243
} else {
224244
log::debug!("No encrypted vars found");
225-
Ok(vars.unwrap_or_default())
245+
let mut ret = LinkedHashMap::<String, Variable>::new();
246+
match vars {
247+
Some(vars) => {
248+
for (k, v) in vars {
249+
ret.insert(k, Variable::ClearText { value: v });
250+
}
251+
Ok(ret)
252+
}
253+
None => Ok(ret),
254+
}
226255
}
227256
}
228257

258+
pub fn variables_to_string(
259+
&self,
260+
vars: &LinkedHashMap<String, Variable>,
261+
) -> LinkedHashMap<String, String> {
262+
let mut ret = LinkedHashMap::<String, String>::new();
263+
for (k, v) in vars {
264+
ret.insert(k.clone(), v.to_string());
265+
}
266+
ret
267+
}
268+
229269
pub async fn edit(&self, workspace_key: &str) -> Result<(), AnyError> {
230270
let labels = Labels::new(Some(workspace_key), Some(WORK_ROLE));
231271
for c in self.api.container.get_all(&labels).await? {
@@ -234,15 +274,36 @@ impl<'a> WorkspaceApi<'a> {
234274
let format = FileFormat::from_path(config_source);
235275
let config =
236276
RoozCfg::deserialize_config(&labels[labels::CONFIG_BODY], format)?.unwrap();
277+
let decrypted = self.decrypt(config.clone().vars).await?;
237278
let decrypted_config = RoozCfg {
238-
vars: Some(self.decrypt(config.clone().vars).await?),
279+
vars: Some(self.variables_to_string(&decrypted)),
239280
..config
240281
};
241-
let edited_config = edit::edit(decrypted_config.to_string(format)?)?;
242-
243-
println!("edited: {}", edited_config);
282+
let edited_string = edit::edit(decrypted_config.to_string(format)?)?;
283+
284+
let edited_config = RoozCfg::from_string(&edited_string, format)?;
285+
286+
let identity = self.read_age_identity().await?;
287+
288+
let mut encrypted_vars = LinkedHashMap::<String, String>::new();
289+
for (k, v) in &decrypted {
290+
let edited_value = &edited_config.clone().vars.unwrap()[k];
291+
match v {
292+
Variable::ClearText { .. } => {
293+
encrypted_vars.insert(k.to_string(), edited_value.to_string())
294+
}
295+
Variable::Secret { .. } => encrypted_vars.insert(
296+
k.to_string(),
297+
self.encrypt_value(identity.clone(), edited_value.to_string())?,
298+
),
299+
};
300+
}
301+
let encrypted_config = RoozCfg {
302+
vars: Some(encrypted_vars),
303+
..edited_config
304+
};
244305

245-
// encrypt
306+
println!("{}", encrypted_config.to_string(format)?)
246307
// save to label
247308
// apply
248309
}

src/cmd/new.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ impl<'a> WorkspaceApi<'a> {
3030
}
3131
cfg_builder.from_cli(cli_params, None);
3232

33-
cfg_builder.vars = Some(self.decrypt(cfg_builder.clone().vars).await?);
33+
cfg_builder.vars =
34+
Some(self.variables_to_string(&self.decrypt(cfg_builder.clone().vars).await?));
3435

3536
cfg_builder.expand_vars()?;
3637

src/main.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,8 @@ async fn main() -> Result<(), AnyError> {
220220
if let Some(vars) = cfg.vars {
221221
if vars.contains_key(&name) {
222222
let identity = workspace.read_age_identity().await?;
223-
let pub_key = identity.to_public();
224-
let encrypted = age_utils::encrypt(vars[&name].to_string(), pub_key)?;
225-
let mut new_vars = vars.clone();
226-
new_vars.insert(name, encrypted);
227223
RoozCfg {
228-
vars: Some(new_vars),
224+
vars: Some(workspace.encrypt(identity, &name, vars)?),
229225
..cfg
230226
}
231227
.to_file(&config_file_path)?

src/model/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl RoozCfg {
123123
Self::from_string(&fs::read_to_string(path)?, FileFormat::from_path(&path))
124124
}
125125

126-
fn from_string(config: &str, file_format: FileFormat) -> Result<Self, AnyError> {
126+
pub fn from_string(config: &str, file_format: FileFormat) -> Result<Self, AnyError> {
127127
Ok(match file_format {
128128
FileFormat::Yaml => serde_yaml::from_str(&config)?,
129129
FileFormat::Toml => toml::from_str(&config)?,

0 commit comments

Comments
 (0)