From 0920c4d4f30a3345870d385d5c6f3e0919228b56 Mon Sep 17 00:00:00 2001 From: benj Date: Mon, 12 Dec 2022 17:06:57 -0800 Subject: (oauth2 + email added): a mess that may or may not really work and needs to be refactored... --- crates/iam/src/main.rs | 108 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 23 deletions(-) (limited to 'crates/iam/src/main.rs') diff --git a/crates/iam/src/main.rs b/crates/iam/src/main.rs index c187380..85b3e37 100644 --- a/crates/iam/src/main.rs +++ b/crates/iam/src/main.rs @@ -2,10 +2,17 @@ mod api; mod command; mod util; -use api::{AdminAction, Args, CliError, Command, CreateObject, GetObject, LinkObject, ListObject}; +use anyhow::bail; +use api::{ + AdminAction, AdminObject, Args, CliError, Command, CreateObject, DevObject, GetObject, + LinkObject, ListObject, Validation, +}; use clap::Parser; +use command::dev_oauth2_listen; +use env_logger::Env; use secd::{Secd, SecdError}; -use util::Result; +use util::{error_detail, Result}; +use uuid::Uuid; use crate::api::ValidationMethod; @@ -15,8 +22,9 @@ const CONFIG_LOGIN_TEMPLATE: &str = "default_login.html"; const CONFIG_SIGNUP_TEMPLATE: &str = "default_signup.html"; const ISSUE_TRACKER_LOC: &str = "https://www.github.com/secdiam/iam"; -#[async_std::main] +#[tokio::main] async fn main() { + env_logger::init_from_env(Env::default().default_filter_or("debug")); match exec().await { Ok(Some(s)) => println!("{}", s), Err(e) => { @@ -30,10 +38,15 @@ async fn main() { async fn exec() -> Result> { let args = Args::parse(); Ok(match args.command { - Command::Init { interactive } => admin(AdminAction::Init { interactive }) - .await - .map_err(|_| CliError::AdminInitializationError)?, - Command::Admin { action } => admin(action).await?, + Command::Init { interactive } + | Command::Admin { + action: AdminAction::Init { interactive }, + } => { + command::admin_init(interactive) + .await + .map_err(|_| CliError::AdminInitializationError)?; + None + } rest @ _ => { let cfg = util::read_config(args.profile).map_err(|_| CliError::InvalidProfile)?; @@ -48,8 +61,14 @@ async fn exec() -> Result> { .map_err(|e| CliError::SecdInitializationFailure(e.to_string()))?; match rest { + Command::Admin { action } => admin(&secd, action).await?, Command::Create { object } => create(&secd, object).await?, + Command::Dev { object } => dev(object).await?, Command::Get { object } => get(&secd, object).await?, + Command::Init { .. } => bail!(CliError::InternalError(error_detail( + "4a696b66-6231-4a2f-811c-4448a41473d2", + "Code path should be unreachable", + ))), Command::Link { object, unlink } => link(&secd, object, unlink).await?, Command::Ls { object, @@ -60,28 +79,30 @@ async fn exec() -> Result> { Command::Repl => { unimplemented!() } - _ => None, } } }) } -async fn admin(cmd: AdminAction) -> Result> { +async fn admin(secd: &Secd, cmd: AdminAction) -> Result> { Ok(match cmd { AdminAction::Backend { action } => { println!("do backend stuff!"); None } - AdminAction::Create { object } => { - println!("do create!"); - None - } - AdminAction::Init { interactive } => { - command::admin_init(interactive) - .await - .map_err(|_| CliError::AdminInitializationError)?; - None - } + AdminAction::Create { object } => match object { + AdminObject::Oauth2Provider { + provider, + client_id, + secret, + redirect_url, + } => { + secd.create_oauth_provider(&provider, client_id, secret, redirect_url) + .await?; + None + } + rest @ _ => unimplemented!(), + }, AdminAction::Seal => { println!("do seal"); None @@ -90,6 +111,9 @@ async fn admin(cmd: AdminAction) -> Result> { println!("do unseal: {}", secret_key); None } + AdminAction::Init { .. } => { + panic!("Invariant violation: this path should be impossible") + } }) } async fn create(secd: &Secd, cmd: CreateObject) -> Result> { @@ -130,19 +154,57 @@ async fn create(secd: &Secd, cmd: CreateObject) -> Result> { .await .map_err(|e| match e { SecdError::InvalidCode => CliError::InvalidCode, - _ => CliError::Unknown, + _ => CliError::InternalError(error_detail( + "17e5c226-5d7d-44a2-b3b5-be3ee958c252", + "An unknown error while exchanging a session", + )), })?; serde_json::to_string(&session).ok() } CreateObject::Validation { method, identity } => match method { - ValidationMethod::Email { address } => { - secd.create_validation_request(Some(&address)).await?; - None + ValidationMethod::Email { address } => serde_json::to_string(&Validation { + validation_id: secd.create_validation_request_email(Some(&address)).await?, + note: Some(" sent to client".into()), + oauth_auth_url: None, + }) + .ok(), + + ValidationMethod::Oauth2 { + provider, + scope, + identity, + } => { + let redirect = secd + .create_validation_request_oauth(&provider, scope) + .await? + .to_string(); + let validation_id = redirect + .split("state=") + .collect::>() + .last() + .map(|i| Uuid::parse_str(i).ok()) + .flatten() + .unwrap(); + serde_json::to_string(&Validation { + validation_id, + note: Some( + " is retrieved by completing oauth flow in the browser".into(), + ), + oauth_auth_url: Some(redirect), + }) + .ok() } _ => unimplemented!(), }, }) } + +async fn dev(cmd: DevObject) -> Result> { + Ok(match cmd { + DevObject::Oauth2Server { port } => serde_json::to_string(&dev_oauth2_listen(port)?).ok(), + }) +} + async fn get(secd: &Secd, cmd: GetObject) -> Result> { Ok(match cmd { GetObject::ApiKey { public_key } => { -- cgit v1.2.3