From 8de1eae2b49d763dcac55b8a2a84673475a35e63 Mon Sep 17 00:00:00 2001 From: Cara Salter Date: Tue, 28 Jun 2022 07:07:34 -0400 Subject: auth: Scaffold auth/begin [WIP] --- .envrc | 1 - Cargo.lock | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 10 ++ flake.nix | 5 - src/errors.rs | 12 ++- src/handlers/auth.rs | 34 +++++++ src/handlers/mod.rs | 1 + src/main.rs | 21 ++++ 8 files changed, 345 insertions(+), 8 deletions(-) delete mode 100644 .envrc create mode 100644 src/handlers/auth.rs diff --git a/.envrc b/.envrc deleted file mode 100644 index 3550a30..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake diff --git a/Cargo.lock b/Cargo.lock index a23cdeb..7242c13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -127,6 +136,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake2" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" +dependencies = [ + "crypto-mac", + "digest", + "opaque-debug", +] + [[package]] name = "bumpalo" version = "3.10.0" @@ -157,6 +177,54 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f08493fa7707effc63254c66c6ea908675912493cd67952eda23c09fae2610b1" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6547abe025f4027edacd9edaa357aded014eecec42a5070d9b885c3c334aba2" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "color-eyre" version = "0.6.1" @@ -200,6 +268,34 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "either" version = "1.6.1" @@ -225,6 +321,28 @@ dependencies = [ "once_cell", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fastrand" version = "1.7.0" @@ -313,6 +431,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.6" @@ -696,6 +824,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -721,6 +868,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl" version = "0.10.40" @@ -795,6 +948,23 @@ dependencies = [ "windows-sys 0.34.0", ] +[[package]] +name = "paseto" +version = "2.0.2+1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04a17c4dbcb8f4a6b17b390aa66ac8e335349f829488950e95617f4b28d72b1f" +dependencies = [ + "base64", + "blake2", + "chacha20poly1305", + "chrono", + "failure", + "failure_derive", + "openssl", + "ring", + "serde_json", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -839,6 +1009,17 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -971,6 +1152,21 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "ructe" version = "0.14.0" @@ -1128,6 +1324,8 @@ dependencies = [ "eyre", "hyper", "kankyo", + "paseto", + "rand", "reqwest", "serde", "solarlib", @@ -1137,12 +1335,13 @@ dependencies = [ "tower-http 0.3.0", "tracing", "tracing-subscriber", + "uuid", ] [[package]] name = "solarlib" version = "1.5.0" -source = "git+https://git.carathe.dev/solard/solarlib?branch=master#373f5f25375d6eb563e5c75f432d78ee7d37672c" +source = "git+https://git.carathe.dev/solard/solarlib?branch=master#945991ae5227bf3de7d715e4d256e11f1753e4fa" dependencies = [ "mac_address", "rand", @@ -1154,6 +1353,18 @@ dependencies = [ "virt", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.91" @@ -1171,6 +1382,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -1214,6 +1437,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1430,6 +1663,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -1451,6 +1690,22 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -1485,6 +1740,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "virt" version = "0.2.11" @@ -1707,3 +1968,9 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/Cargo.toml b/Cargo.toml index c1a8255..0b2ead9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,10 @@ kankyo = "0.3" axum-macros = "0.2" +paseto = "2" + +rand = "0.8" + [dependencies.solarlib] git = "https://git.carathe.dev/solard/solarlib" branch = "master" @@ -52,3 +56,9 @@ features = [ "json", "blocking" ] + +[dependencies.uuid] +version = "1" +features = [ + "v4" +] diff --git a/flake.nix b/flake.nix index e2a9595..e7abd18 100644 --- a/flake.nix +++ b/flake.nix @@ -90,11 +90,6 @@ }; }; - - # `nix develop` - devShell = pkgs.mkShell { - nativeBuildInputs = with pkgs; [ rustc cargo ] ++ deps; - }; } ); } diff --git a/src/errors.rs b/src/errors.rs index e0a6df9..cbec046 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -20,7 +20,16 @@ pub enum ServiceError { Reqwest(#[from] reqwest::Error), #[error("Command error: {0}")] - Command(#[from] std::io::Error) + Command(#[from] std::io::Error), + + #[error("Not authorized")] + NotAuthorized, + + #[error("Generic: {0}")] + Generic(String), + + #[error("Paseto: {0}")] + Paseto(#[from] pasetors::errors::Error), } pub type StringResult = std::result::Result; @@ -35,6 +44,7 @@ impl IntoResponse for ServiceError { let status = match self { ServiceError::NotFound => StatusCode::NOT_FOUND, + ServiceError::NotAuthorized => StatusCode::UNAUTHORIZED, _ => StatusCode::INTERNAL_SERVER_ERROR, }; Response::builder() diff --git a/src/handlers/auth.rs b/src/handlers/auth.rs new file mode 100644 index 0000000..a9ac394 --- /dev/null +++ b/src/handlers/auth.rs @@ -0,0 +1,34 @@ +use std::collections::HashMap; + +use axum::{extract::Query, Extension}; +use axum_macros::debug_handler; +use pasetors::{claims::Claims, keys::{AsymmetricKeyPair, Generate}, version4::V4}; +use uuid::Uuid; + +use crate::{errors::{NoneResult, ServiceError}, State}; + + +/** + * Takes in a request to create a new token with a secret key that gets printed + * to stdout and, if it matches, returns a valid PASETO token that can be used + * for future authentication + */ +#[debug_handler] +pub async fn begin(Query(params): Query>, Extension(state): Extension) -> NoneResult { + if let Some(k) = params.get("key") { + if k == &state.gen_key { + let mut claims = Claims::new()?; + claims.non_expiring(); + claims.audience("solard")?; + claims.add_additional("uuid", Uuid::new_v4().to_string())?; + + let kp = AsymmetricKeyPair::::generate()?; + } else { + return Err(ServiceError::NotAuthorized); + } + } else { + return Err(ServiceError::Generic("No key supplied".to_string())); + } + + Ok(()) +} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 591f76e..8f8224e 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1 +1,2 @@ pub mod planets; +pub mod auth; diff --git a/src/main.rs b/src/main.rs index 4dc78a6..3f889cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use axum::{ Json, Router, Extension }; +use rand::{thread_rng, Rng, distributions::Alphanumeric}; use serde::{Deserialize, Serialize}; use solarlib::star::Star; use std::{net::SocketAddr, time::Duration, str::FromStr, sync::Arc}; @@ -20,8 +21,11 @@ mod errors; mod handlers; +#[derive(Clone)] pub struct State { pub hw_url: String, + pub secret_key: String, + pub gen_key: String, } #[tokio::main] @@ -36,10 +40,25 @@ async fn main() { .with(tracing_subscriber::fmt::layer()) .init(); + let rand_key: String = thread_rng() + .sample_iter(&Alphanumeric) + .take(30) + .map(char::from) + .collect(); + let shared_state = Arc::new(State { hw_url: std::env::var("HOMEWORLD_URL").expect("No Homeworld URL set"), + secret_key: std::env::var("SECRET_KEY").unwrap_or("bad-key".to_string()), + gen_key: rand_key, }); + if shared_state.secret_key == "bad-key" { + tracing::warn!("No secret key set! This is a bad idea."); + tracing::warn!("Using default of `bad-key`"); + } + + tracing::info!("Random Key: {}", shared_state.gen_key); + let app = Router::new() .route("/health", get(health_check)) .route("/planets/list", get(handlers::planets::list)) @@ -52,6 +71,8 @@ async fn main() { .route("/planets/:uuid/reboot", post(handlers::planets::reboot)) .route("/planets/:uuid/reboot/hard", post(handlers::planets::force_reboot)) .route("/planets/:uuid/destroy", post(handlers::planets::no_planet)) + // Authentication + .route("/auth/begin", post(handlers::auth::begin)) .layer( ServiceBuilder::new() .layer(HandleErrorLayer::new(|error: BoxError| async move { if error.is::() { -- cgit v1.2.3