Skip to content
This repository was archived by the owner on Oct 31, 2023. It is now read-only.

Commit a974cb1

Browse files
authoredNov 3, 2020
Claims autogeneration, optional autogeneration (#11)
* added autogeneration to claims sign, allow disabling autogeneration of keys * bumped version, fixed duplicate argument error * reversed incorrect logic for autogeneration
1 parent 2bb9002 commit a974cb1

File tree

4 files changed

+125
-68
lines changed

4 files changed

+125
-68
lines changed
 

‎Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "wash"
3-
version = "0.1.3"
3+
version = "0.1.4"
44
authors = ["Brooks Townsend <brooksmtownsend@gmail.com>"]
55
edition = "2018"
66
repository = "https://github.com/wascc/wash"

‎src/claims.rs

+92-53
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
// extern crate serde_derive;
1616

17-
use nkeys::KeyPair;
17+
use crate::keys::extract_keypair;
18+
use nkeys::{KeyPair, KeyPairType};
1819
use serde::de::DeserializeOwned;
1920
use serde::{Deserialize, Serialize};
2021
use std::collections::HashMap;
2122
use std::fs::{read_to_string, File};
2223
use std::io::Read;
2324
use std::io::Write;
25+
use std::path::PathBuf;
2426
use structopt::clap::AppSettings;
2527
use structopt::StructOpt;
2628
use term_table::{
@@ -63,6 +65,30 @@ enum ClaimsCliCommand {
6365
Token(TokenCommand),
6466
}
6567

68+
#[derive(StructOpt, Debug, Clone)]
69+
struct SignCommand {
70+
/// File to read
71+
source: String,
72+
/// Target output file. If this flag is not provided, the signed module will be placed in the same directory as the source with a "_s" suffix
73+
#[structopt(short = "o", long = "output")]
74+
output: Option<String>,
75+
76+
// /// Location of key files for signing. Defaults to $WASH_KEYS ($HOME/.wash/keys)
77+
// #[structopt(
78+
// short = "d",
79+
// long = "directory",
80+
// env = "WASH_KEYS",
81+
// hide_env_values = true
82+
// )]
83+
// directory: Option<String>,
84+
/// Disables autogeneration of signing keys
85+
#[structopt(long = "disable-keygen")]
86+
disable_keygen: bool,
87+
88+
#[structopt(flatten)]
89+
metadata: ActorMetadata,
90+
}
91+
6692
#[derive(Debug, Clone, StructOpt)]
6793
enum TokenCommand {
6894
/// Generate a signed JWT for an actor module
@@ -81,13 +107,22 @@ enum TokenCommand {
81107

82108
#[derive(Debug, Clone, StructOpt, Serialize, Deserialize)]
83109
struct GenerateCommon {
84-
/// Issuer seed key path (usually a .nk file)
110+
/// Path to issuer seed key. If this flag is not provided, the will be sourced from $WASH_KEYS ($HOME/.wash/keys) or generated for you if it cannot be found.
85111
#[structopt(short = "i", long = "issuer")]
86-
issuer_key_path: String,
112+
issuer: Option<String>,
87113

88-
/// Subject seed key path (usually a .nk file)
114+
/// Path to subject seed key. If this flag is not provided, the will be sourced from $WASH_KEYS ($HOME/.wash/keys) or generated for you if it cannot be found.
89115
#[structopt(short = "u", long = "subject")]
90-
subject_key_path: String,
116+
subject: Option<String>,
117+
118+
/// Location of key files for signing. Defaults to $WASH_KEYS ($HOME/.wash/keys)
119+
#[structopt(
120+
short = "d",
121+
long = "directory",
122+
env = "WASH_KEYS",
123+
hide_env_values = true
124+
)]
125+
directory: Option<String>,
91126

92127
/// Indicates the token expires in the given amount of days. If this option is left off, the token will never expire
93128
#[structopt(short = "x", long = "expires")]
@@ -223,17 +258,6 @@ struct ActorMetadata {
223258
common: GenerateCommon,
224259
}
225260

226-
#[derive(StructOpt, Debug, Clone)]
227-
struct SignCommand {
228-
/// File to read
229-
source: String,
230-
/// Target output file
231-
output: String,
232-
233-
#[structopt(flatten)]
234-
metadata: ActorMetadata,
235-
}
236-
237261
pub fn handle_command(cli: ClaimsCli) -> Result<(), Box<dyn ::std::error::Error>> {
238262
match cli.command {
239263
ClaimsCliCommand::Inspect { file, raw } => render_caps(&file, raw),
@@ -262,25 +286,22 @@ fn get_keypair_vec(paths: &[String]) -> Result<Vec<KeyPair>, Box<dyn ::std::erro
262286
.collect())
263287
}
264288

265-
fn get_keypairs(
266-
common: &GenerateCommon,
267-
) -> Result<(KeyPair, KeyPair), Box<dyn ::std::error::Error>> {
268-
if common.issuer_key_path.is_empty() {
269-
return Err("Must specify an issuer key path".into());
270-
}
271-
if common.subject_key_path.is_empty() {
272-
return Err("Must specify a subject key path".into());
273-
}
274-
let iss_key = read_to_string(&common.issuer_key_path)?;
275-
let sub_key = read_to_string(&common.subject_key_path)?;
276-
let issuer = KeyPair::from_seed(iss_key.trim_end())?;
277-
let subject = KeyPair::from_seed(sub_key.trim_end())?;
278-
279-
Ok((issuer, subject))
280-
}
281-
282289
fn generate_actor(actor: &ActorMetadata) -> Result<(), Box<dyn ::std::error::Error>> {
283-
let (issuer, subject) = get_keypairs(&actor.common)?;
290+
let issuer = extract_keypair(
291+
actor.common.issuer.clone(),
292+
None,
293+
actor.common.directory.clone(),
294+
KeyPairType::Account,
295+
true,
296+
)?;
297+
let subject = extract_keypair(
298+
actor.common.subject.clone(),
299+
None,
300+
actor.common.directory.clone(),
301+
KeyPairType::Module,
302+
true,
303+
)?;
304+
284305
let mut caps_list = vec![];
285306
if actor.keyvalue {
286307
caps_list.push(wascap::caps::KEY_VALUE.to_string());
@@ -397,21 +418,20 @@ fn sign_file(cmd: &SignCommand) -> Result<(), Box<dyn ::std::error::Error>> {
397418
let mut buf = Vec::new();
398419
sfile.read_to_end(&mut buf).unwrap();
399420

400-
let mod_kp = if !cmd.metadata.common.subject_key_path.is_empty() {
401-
KeyPair::from_seed(&read_to_string(&cmd.metadata.common.subject_key_path)?.trim_end())?
402-
} else {
403-
let m = KeyPair::new_module();
404-
println!("New module key created. SAVE this seed key: {}", m.seed()?);
405-
m
406-
};
407-
408-
let acct_kp = if !cmd.metadata.common.issuer_key_path.is_empty() {
409-
KeyPair::from_seed(&read_to_string(&cmd.metadata.common.issuer_key_path)?.trim_end())?
410-
} else {
411-
let a = KeyPair::new_account();
412-
println!("New account key created. SAVE this seed key: {}", a.seed()?);
413-
a
414-
};
421+
let issuer = extract_keypair(
422+
cmd.metadata.common.issuer.clone(),
423+
Some(cmd.source.clone()),
424+
cmd.metadata.common.directory.clone(),
425+
KeyPairType::Account,
426+
cmd.disable_keygen,
427+
)?;
428+
let subject = extract_keypair(
429+
cmd.metadata.common.subject.clone(),
430+
Some(cmd.source.clone()),
431+
cmd.metadata.common.directory.clone(),
432+
KeyPairType::Module,
433+
cmd.disable_keygen,
434+
)?;
415435

416436
let mut caps_list = vec![];
417437
if cmd.metadata.keyvalue {
@@ -447,8 +467,8 @@ fn sign_file(cmd: &SignCommand) -> Result<(), Box<dyn ::std::error::Error>> {
447467
let signed = sign_buffer_with_claims(
448468
cmd.metadata.name.clone(),
449469
&buf,
450-
mod_kp,
451-
acct_kp,
470+
issuer,
471+
subject,
452472
cmd.metadata.common.expires_in_days,
453473
cmd.metadata.common.not_before_days,
454474
caps_list.clone(),
@@ -458,12 +478,31 @@ fn sign_file(cmd: &SignCommand) -> Result<(), Box<dyn ::std::error::Error>> {
458478
cmd.metadata.ver.clone(),
459479
)?;
460480

461-
let mut outfile = File::create(&cmd.output).unwrap();
481+
let output = match cmd.output.clone() {
482+
Some(out) => out,
483+
None => {
484+
let path = PathBuf::from(cmd.source.clone())
485+
.parent()
486+
.unwrap()
487+
.to_str()
488+
.unwrap()
489+
.to_string();
490+
let module_name = PathBuf::from(cmd.source.clone())
491+
.file_stem()
492+
.unwrap()
493+
.to_str()
494+
.unwrap()
495+
.to_string();
496+
format!("{}/{}_s.wasm", path, module_name)
497+
}
498+
};
499+
500+
let mut outfile = File::create(&output).unwrap();
462501
match outfile.write(&signed) {
463502
Ok(_) => {
464503
println!(
465504
"Successfully signed {} with capabilities: {}",
466-
cmd.output,
505+
output,
467506
caps_list.join(",")
468507
);
469508
Ok(())

‎src/keys.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,10 @@ fn determine_directory(directory: Option<String>) -> String {
170170
/// Helper function to locate and extract keypair from user input
171171
pub fn extract_keypair(
172172
input: Option<String>,
173-
module_path: String,
173+
module_path: Option<String>,
174174
directory: Option<String>,
175175
keypair_type: KeyPairType,
176+
disable_keygen: bool,
176177
) -> Result<KeyPair, Box<dyn std::error::Error>> {
177178
let seed = if let Some(input_str) = input {
178179
match File::open(input_str.clone()) {
@@ -185,10 +186,10 @@ pub fn extract_keypair(
185186
// User provided seed as an argument
186187
Err(_e) => input_str,
187188
}
188-
} else {
189+
} else if let Some(module) = module_path {
189190
// No seed value provided, attempting to source from provided or default directory
190191
let dir = determine_directory(directory);
191-
let module_name = PathBuf::from(module_path)
192+
let module_name = PathBuf::from(module)
192193
.file_stem()
193194
.unwrap()
194195
.to_str()
@@ -208,23 +209,28 @@ pub fn extract_keypair(
208209
s
209210
}
210211
// No default key, generating for user
211-
Err(_e) => {
212+
Err(_e) if !disable_keygen => {
212213
let kp = KeyPair::new(keypair_type);
213-
println!("No keypair found in {}, we will generate one for you and place it there. If you'd like to use alternative keys, you can supply them as a flag.", path);
214+
println!("No keypair found in \"{}\".\nWe will generate one for you and place it there.\nIf you'd like to use alternative keys, you can supply them as a flag.\n", path);
214215
let seed = kp.seed()?;
215216
fs::create_dir_all(Path::new(&path).parent().unwrap())?;
216217
let mut f = File::create(path)?;
217218
f.write_all(seed.as_bytes())?;
218219
seed
219220
}
221+
_ => {
222+
return Err(format!(
223+
"No keypair found in {}, please ensure key exists or supply one as a flag",
224+
path
225+
)
226+
.into());
227+
}
220228
}
229+
} else {
230+
return Err("Keypair path or string not supplied. Ensure provided keypair is valid".into());
221231
};
222232

223-
// from_seed returns nkeys::error::Error
224-
match KeyPair::from_seed(&seed) {
225-
Ok(kp) => Ok(kp),
226-
Err(e) => Err(e.into()),
227-
}
233+
KeyPair::from_seed(&seed).map_err(|e| format!("{}", e).into())
228234
}
229235

230236
fn keypair_type_to_string(keypair_type: KeyPairType) -> String {

‎src/par.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ struct CreateCommand {
8888
/// Include a compressed provider archive
8989
#[structopt(long = "compress")]
9090
compress: bool,
91+
92+
/// Disables autogeneration of signing keys
93+
#[structopt(long = "disable-keygen")]
94+
disable_keygen: bool,
9195
}
9296

9397
#[derive(StructOpt, Debug, Clone)]
@@ -127,6 +131,10 @@ struct InsertCommand {
127131
/// Path to subject seed key (service). If this flag is not provided, the will be sourced from $WASH_KEYS ($HOME/.wash/keys) or generated for you if it cannot be found.
128132
#[structopt(short = "s", long = "subject")]
129133
subject: Option<String>,
134+
135+
/// Disables autogeneration of signing keys
136+
#[structopt(long = "disable-keygen")]
137+
disable_keygen: bool,
130138
}
131139

132140
pub fn handle_command(cli: ParCli) -> Result<()> {
@@ -153,15 +161,17 @@ fn handle_create(cmd: CreateCommand) -> Result<()> {
153161

154162
let issuer = extract_keypair(
155163
cmd.issuer,
156-
cmd.binary.clone(),
164+
Some(cmd.binary.clone()),
157165
cmd.directory.clone(),
158166
KeyPairType::Account,
167+
cmd.disable_keygen,
159168
)?;
160169
let subject = extract_keypair(
161170
cmd.subject,
162-
cmd.binary.clone(),
171+
Some(cmd.binary.clone()),
163172
cmd.directory,
164173
KeyPairType::Service,
174+
cmd.disable_keygen,
165175
)?;
166176

167177
par.add_library(&cmd.arch, &lib)
@@ -254,15 +264,17 @@ fn handle_insert(cmd: InsertCommand) -> Result<()> {
254264

255265
let issuer = extract_keypair(
256266
cmd.issuer,
257-
cmd.binary.clone(),
267+
Some(cmd.binary.clone()),
258268
cmd.directory.clone(),
259269
KeyPairType::Account,
270+
cmd.disable_keygen,
260271
)?;
261272
let subject = extract_keypair(
262273
cmd.subject,
263-
cmd.binary.clone(),
274+
Some(cmd.binary.clone()),
264275
cmd.directory,
265276
KeyPairType::Service,
277+
cmd.disable_keygen,
266278
)?;
267279

268280
let mut f = File::open(cmd.binary.clone())?;

0 commit comments

Comments
 (0)
This repository has been archived.