Include the key-rotater project in the monorepo
This commit is contained in:
parent
878ff48d95
commit
42d2705a84
4 changed files with 100 additions and 0 deletions
1
key-rotater/.gitignore
vendored
Normal file
1
key-rotater/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
10
key-rotater/Cargo.toml
Normal file
10
key-rotater/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "debt-pirate-key-rotater"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22.1"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
humantime = "2.1"
|
||||
pasetors = "0.7"
|
9
key-rotater/README.md
Normal file
9
key-rotater/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Debt Pirate Key Rotater
|
||||
|
||||
Creates new PASETO keys for use in the API
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
$ dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | xargs cargo run --
|
||||
```
|
80
key-rotater/src/main.rs
Normal file
80
key-rotater/src/main.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use std::{
|
||||
env,
|
||||
io::{self, BufRead, Write},
|
||||
process,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
use base64::prelude::*;
|
||||
use humantime::format_rfc3339_seconds;
|
||||
use pasetors::{
|
||||
keys::SymmetricKey,
|
||||
paserk::{FormatAsPaserk, Id},
|
||||
version4::V4,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let encoded_secret = read_secret();
|
||||
let secret = if let Ok(secret) = decode_secret(encoded_secret) {
|
||||
secret
|
||||
} else {
|
||||
eprintln!("Not a valid 32-byte, base64 encoded string.");
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
let (id, key) = generate_local_key(secret.as_slice());
|
||||
let mut id_string = String::new();
|
||||
id.fmt(&mut id_string).unwrap();
|
||||
|
||||
let one_year: Duration = Duration::from_secs_f64(60_f64 * 60_f64 * 24_f64 * 365.25_f64);
|
||||
let expiration = format_rfc3339_seconds(SystemTime::now() + one_year);
|
||||
|
||||
println!("ID: {id_string}\nKey: {key}\nExpiration: {expiration}");
|
||||
}
|
||||
|
||||
fn read_secret() -> String {
|
||||
let secret_arg = env::args().skip(1).last();
|
||||
|
||||
let secret = if let Some(secret) = secret_arg {
|
||||
secret
|
||||
} else {
|
||||
print!("Enter a 32-byte, base64 encoded string: ");
|
||||
let _ = io::stdout().flush();
|
||||
|
||||
let mut buffer = String::with_capacity(32);
|
||||
let stdin = io::stdin();
|
||||
|
||||
stdin.lock().read_line(&mut buffer).unwrap();
|
||||
buffer
|
||||
.strip_suffix("\r\n")
|
||||
.or(buffer.strip_suffix("\n"))
|
||||
.map(|buffer| buffer.to_owned())
|
||||
.unwrap_or(buffer)
|
||||
};
|
||||
|
||||
secret
|
||||
}
|
||||
|
||||
fn decode_secret(secret: String) -> Result<Vec<u8>, ()> {
|
||||
BASE64_STANDARD
|
||||
.decode(secret)
|
||||
.map_err(|_| ())
|
||||
.and_then(|secret| {
|
||||
if secret.len() != 32 {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(secret)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_local_key(secret: &[u8]) -> (Id, String) {
|
||||
let key = SymmetricKey::<V4>::from(secret).unwrap();
|
||||
|
||||
let mut serialized_key = String::with_capacity(54);
|
||||
let _ = key.fmt(&mut serialized_key);
|
||||
|
||||
let id = Id::from(&key);
|
||||
|
||||
(id, serialized_key)
|
||||
}
|
Loading…
Add table
Reference in a new issue