summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-06-20 22:50:09 -0400
committerGalen Guyer <galen@galenguyer.com>2022-06-20 22:50:09 -0400
commit0ba4f8fc438c93666b8ee3f9caec615c97a385b0 (patch)
treefd69448a98d753b61b115f4b457e477cc5ef7de1
parenta850fd3ebd41bf6f7591ee5512bfb1c0808f0e0b (diff)
add list command
-rw-r--r--src/cli.rs2
-rw-r--r--src/lib/ops.rs69
2 files changed, 71 insertions, 0 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 0e4e064..a4c7513 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -14,6 +14,7 @@ pub struct Cli {
pub enum Commands {
Init(Init),
Issue(Issue),
+ List(List),
}
fn main() {
@@ -22,5 +23,6 @@ fn main() {
match cli.command {
Commands::Init(args) => init(args),
Commands::Issue(args) => issue(args),
+ Commands::List(args) => list(args),
}
}
diff --git a/src/lib/ops.rs b/src/lib/ops.rs
index 8abe832..efb739a 100644
--- a/src/lib/ops.rs
+++ b/src/lib/ops.rs
@@ -1,4 +1,8 @@
use clap::Args;
+use openssl::asn1::Asn1Time;
+use openssl::nid::Nid;
+use std::cmp::Ordering;
+use std::fs;
use std::path::Path;
use crate::KeyType;
@@ -104,6 +108,13 @@ pub struct Issue {
pub password: Option<String>,
}
+#[derive(Args, Debug)]
+#[clap(about = "List all known certificates")]
+pub struct List {
+ #[clap(long, default_value = "~/.hancock", env = "CA_BASE_DIR")]
+ pub base_dir: String,
+}
+
pub fn init(args: Init) {
let base_dir = path::base_dir(&args.base_dir);
@@ -196,6 +207,64 @@ pub fn issue(args: Issue) {
);
}
+pub fn list(args: List) {
+ let base_dir = path::base_dir(&args.base_dir);
+
+ let rsa_ca_crt_path = path::ca_crt(&base_dir, KeyType::Rsa(0));
+ if Path::new(&rsa_ca_crt_path).is_file() {
+ let crt = cert::read_cert(&rsa_ca_crt_path);
+ println!("{}", cert_info(crt));
+ }
+
+ let ecda_ca_crt_path = path::ca_crt(&base_dir, KeyType::Ecdsa);
+ if Path::new(&ecda_ca_crt_path).is_file() {
+ let crt = cert::read_cert(&ecda_ca_crt_path);
+ println!("{}", cert_info(crt));
+ }
+
+ for name in fs::read_dir(&base_dir).unwrap() {
+ let name = name.unwrap();
+ if name.file_type().unwrap().is_dir() {
+ let name = format!("{}", name.file_name().to_string_lossy());
+ let rsa_crt_path = path::cert_crt(&base_dir, &name, KeyType::Rsa(0));
+ if Path::new(&rsa_crt_path).is_file() {
+ let crt = cert::read_cert(&rsa_crt_path);
+ println!("{}", cert_info(crt));
+ }
+
+ let ecda_crt_path = path::cert_crt(&base_dir, &name, KeyType::Ecdsa);
+ if Path::new(&ecda_crt_path).is_file() {
+ let crt = cert::read_cert(&ecda_crt_path);
+ println!("{}", cert_info(crt));
+ }
+ }
+ }
+}
+
+fn cert_info(crt: openssl::x509::X509) -> String {
+ let now = Asn1Time::days_from_now(0).unwrap();
+
+ let get_cn = |cert: &openssl::x509::X509| -> String {
+ let cn = cert.subject_name().entries_by_nid(Nid::COMMONNAME);
+ for entry in cn {
+ return format!("{}", entry.data().as_utf8().unwrap());
+ }
+ String::from("Unknown CN")
+ };
+
+ let cn = get_cn(&crt);
+ let ex = match now.compare(crt.not_after()).unwrap() {
+ Ordering::Greater => {
+ format!("{} days ago", now.diff(crt.not_after()).unwrap().days)
+ }
+ Ordering::Less => {
+ format!("in {} days", now.diff(crt.not_after()).unwrap().days)
+ }
+ Ordering::Equal => String::from("right now"),
+ };
+ format!("{cn} - expires {ex}")
+}
+
fn validate_key_type(input: &str) -> Result<(), String> {
let input = input.to_string().to_uppercase();
if input == "RSA" || input == "ECDSA" {