diff --git a/Cargo.lock b/Cargo.lock index ee22a5a..d62f8a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,7 +437,7 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vault-unseal" -version = "0.3.0" +version = "0.2.0" dependencies = [ "dotenv", "serde", diff --git a/Cargo.toml b/Cargo.toml index a67543d..96bbe99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vault-unseal" -version = "0.3.0" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.nix b/flake.nix index ce3034b..956bc89 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,8 @@ pname = toml.package.name; version = toml.package.version; src = self; - cargoLock.lockFile = ./Cargo.lock; + cargoSha256 = + "sha256-eOvTR7TpFpi83J3G8HPXgOBryTzkq4XWp6CER6UDCbo="; }; }; }); diff --git a/src/main.rs b/src/main.rs index 9a0b185..b9e0e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use std::{env, fs::File}; use tracing::{info, subscriber, warn}; use tracing_subscriber::FmtSubscriber; use ureq::Error::Status; +use ureq::Response; #[derive(Debug, Deserialize)] struct KeyFile { @@ -16,30 +17,28 @@ struct KeyFile { } #[derive(Debug, Deserialize)] -struct UnsealResponse { +struct HealthCheck { sealed: bool, - t: u8, - n: u8, - progress: u8, } -/// returns true if the vault is sealed -/// -/// see: https://developer.hashicorp.com/vault/api-docs/system/health fn is_sealed(health_url: &str) -> bool { + fn parse_hc(x: Response) -> bool { + match x.into_json() { + Ok(HealthCheck { sealed }) => sealed, + Err(_) => false, + } + } + let resp = ureq::get(health_url).call(); match resp { - Ok(r) if r.status() == 200 => false, - Ok(r) => { - warn!( - "unexpected status code: '{}': {}", - r.status(), - r.status_text() - ); + Ok(x) => parse_hc(x), + Err(Status(503, resp)) => parse_hc(resp), + Err(Status(429, _)) => { + info!("got code 429: too many requests, waiting"); + // too many requests + thread::sleep(Duration::from_secs(15)); false } - Err(Status(429, _)) => false, // Unsealed and standby - Err(Status(503, _)) => true, // Sealed Err(Status(code, resp)) => { info!( "error checking health, got code: '{code}', with message: {}", @@ -48,31 +47,25 @@ fn is_sealed(health_url: &str) -> bool { false } Err(e) => { - warn!("error checking health: {e}"); + warn!("Got error: {e}"); false } } } fn unseal(keyfile: &KeyFile, unseal_url: &str) { - for key in keyfile.keys.iter() { + let len = keyfile.keys.len(); + for (i, key) in keyfile.keys.iter().enumerate() { + let i = i + 1; match ureq::post(unseal_url).send_json(json!({ "key": key })) { Ok(resp) if resp.status() == 200 => { - if let Ok(UnsealResponse { - sealed, - t, - progress, - .. - }) = resp.into_json() - { - if !sealed { - info!("vault unsealed"); - return; - } - info!("unsealed vault partially {progress}/{t}"); + if i < len { + info!("unsealed vault partially {i}/{len}"); + } else { + info!("fully unsealed vault {i}/{len}"); } } - Ok(resp) | Err(Status(_, resp)) => warn!( + Ok(resp) => warn!( "error unsealing vault, got code '{}', with message: {}", resp.status(), resp.status_text()