diff options
| author | benj <benj@rse8.com> | 2023-05-22 15:47:06 -0700 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2023-05-22 15:47:06 -0700 |
| commit | ed34a5251f13bbded0aa15719887db4924b351eb (patch) | |
| tree | 9719d805e915f4483d5db3e5e612e8b4cf5c702c /crates/iam/src/main.rs | |
| parent | eb92f823c31a5e702af7005231f0d6915aad3342 (diff) | |
| download | secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar.gz secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar.bz2 secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar.lz secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar.xz secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.tar.zst secdiam-ed34a5251f13bbded0aa15719887db4924b351eb.zip | |
update credential API to include sessions
This change updates the credential API to include sessions as just another
credential type. It adds the ApiToken type and enables revocation of
credentials. Updates were also made to the Identity API which now includes a
list of new credentials added to an Identity.
This change also migrates off the hacky ENV configuration paradigm and includes
a new config.toml file specified by the SECD_CONFIG_PATH env var. No default is
currently provided.
Clippy updates and code cleanup.
Diffstat (limited to 'crates/iam/src/main.rs')
| -rw-r--r-- | crates/iam/src/main.rs | 143 |
1 files changed, 82 insertions, 61 deletions
diff --git a/crates/iam/src/main.rs b/crates/iam/src/main.rs index c679af6..28f4e4c 100644 --- a/crates/iam/src/main.rs +++ b/crates/iam/src/main.rs @@ -2,19 +2,19 @@ mod api; mod command; mod util; +use crate::api::ValidationMethod; use anyhow::bail; -use api::{AdminAction, Args, CliError, Command, CreateObject, DevObject, GetObject, UpdateObject}; +use api::{ + AdminAction, Args, CliError, Command, CreateObject, DevObject, GetObject, UpdateObject, + ValidateObject, +}; + use clap::Parser; use command::dev_oauth2_listen; use env_logger::Env; -use secd::{ - auth::z, Credential, CredentialType, Secd, ENV_AUTH_STORE_CONN_STRING, ENV_SPICE_SECRET, - ENV_SPICE_SERVER, -}; -use util::{error_detail, Result}; -use uuid::Uuid; - -use crate::api::ValidationMethod; +use secd::{CredentialType, Secd}; +use time::OffsetDateTime; +use util::Result; const CONFIG_DIR_NAME: &str = "secdiam"; const CONFIG_PROFILE_FILE: &str = "profiles.toml"; @@ -49,15 +49,7 @@ async fn exec() -> Result<Option<String>> { rest @ _ => { // let cfg = util::read_config(args.profile).map_err(|_| CliError::InvalidProfile)?; - std::env::set_var( - ENV_AUTH_STORE_CONN_STRING, - // "sqlite:///home/benj/.config/secdiam/34wxC.sql?mode=rwc", - "postgresql://secduser:p4ssw0rd@localhost:5412/secd", - ); - std::env::set_var(ENV_SPICE_SECRET, "sup3rs3cr3tk3y"); - std::env::set_var(ENV_SPICE_SERVER, "http://[::1]:50051"); - - let secd = Secd::init(None) + let secd = Secd::init(None, None) .await .map_err(|e| CliError::SecdInitializationFailure(e.to_string()))?; @@ -70,6 +62,7 @@ async fn exec() -> Result<Option<String>> { unimplemented!() } Command::Update { object } => update(&secd, object).await?, + Command::Validate { object } => validate(&secd, object).await?, } } }) @@ -101,18 +94,27 @@ async fn create(secd: &Secd, cmd: CreateObject) -> Result<Option<String>> { method, identity_id, } => { - let t = match method { + let t = match &method { api::CredentialMethod::Passphrase { username, passphrase, } => CredentialType::Passphrase { - key: username, - value: passphrase, + key: username.clone(), + value: passphrase.clone(), }, + api::CredentialMethod::ApiToken { .. } => CredentialType::new_api_token()?, + }; + + let expires_at = match method { + api::CredentialMethod::ApiToken { expires_at, .. } => expires_at.map(|t| { + OffsetDateTime::from_unix_timestamp(t) + .expect("The provided value is an invalid unix timestamp") + }), + api::CredentialMethod::Passphrase { .. } => None, }; - let credential = secd.create_credential(t, identity_id).await?; - Some(serde_json::ser::to_string(&credential)?.to_string()) + let credential = secd.create_credential(t, identity_id, expires_at).await?; + Some(serde_json::ser::to_string_pretty(&credential)?.to_string()) } CreateObject::Validation { method, @@ -121,7 +123,7 @@ async fn create(secd: &Secd, cmd: CreateObject) -> Result<Option<String>> { ValidationMethod::Email { address } => { let validation = secd.validate_email(&address, identity_id).await?; - Some(serde_json::ser::to_string(&validation)?.to_string()) + Some(serde_json::ser::to_string_pretty(&validation)?.to_string()) } _ => unimplemented!(), }, @@ -136,7 +138,7 @@ async fn create(secd: &Secd, cmd: CreateObject) -> Result<Option<String>> { let session = secd .complete_address_validation(&validation_id, token, code) .await?; - Some(serde_json::ser::to_string(&session)?.to_string()) + Some(serde_json::ser::to_string_pretty(&session)?.to_string()) } }) } @@ -149,44 +151,31 @@ async fn dev(cmd: DevObject) -> Result<Option<String>> { async fn get(secd: &Secd, cmd: GetObject) -> Result<Option<String>> { Ok(match cmd { - GetObject::ApiKey { public_key } => { - println!("get object api key"); - None - } - GetObject::Group { name, id } => { - println!("get object group"); - None - } GetObject::Identity { identity_id, - session_token, - } => Some( - serde_json::ser::to_string(&secd.get_identity(identity_id, session_token).await?)? - .to_string(), - ), - - GetObject::Permission { name, id } => { - println!("get object permission"); - None - } - GetObject::Role { name, id } => { - println!("get object role"); - None - } - GetObject::Service { name, id } => { - println!("get object service"); - None - } - GetObject::ServiceAction { name, id } => { - println!("get object service action"); - None - } - GetObject::Session { secret } => { - Some(serde_json::ser::to_string(&secd.get_session(&secret).await?)?.to_string()) - } - GetObject::Validation { id } => { - println!("get object validation"); - None + + credential, + } => { + let t = credential.map(|cred| match cred { + ValidateObject::ApiToken { token } => { + CredentialType::api_token_from_str(&token).expect("failed to build api token") + } + ValidateObject::Passphrase { + username, + passphrase, + } => CredentialType::Passphrase { + key: username, + value: passphrase, + }, + ValidateObject::Session { token } => { + CredentialType::session_from_str(&token).expect("failed to build session") + } + }); + + Some( + serde_json::ser::to_string_pretty(&secd.get_identity(identity_id, t).await?)? + .to_string(), + ) } }) } @@ -202,5 +191,37 @@ async fn update(secd: &Secd, cmd: UpdateObject) -> Result<Option<String>> { Some(serde_json::to_string(&identity)?.to_string()) } + UpdateObject::Credential { id, revoke } => { + if revoke { + secd.revoke_credential(id).await?; + } + + Some("Ok".to_string()) + } }) } + +async fn validate(secd: &Secd, cmd: ValidateObject) -> Result<Option<String>> { + let credential = match cmd { + ValidateObject::ApiToken { token } => { + secd.validate_credential(CredentialType::api_token_from_str(&token)?) + .await? + } + ValidateObject::Passphrase { + username, + passphrase, + } => { + secd.validate_credential(CredentialType::Passphrase { + key: username, + value: passphrase, + }) + .await? + } + ValidateObject::Session { token } => { + secd.validate_credential(CredentialType::session_from_str(&token)?) + .await? + } + }; + + Ok(Some(serde_json::to_string_pretty(&credential)?.to_string())) +} |
