243 lines
7.4 KiB
Rust
243 lines
7.4 KiB
Rust
use oauth::{OAuth, ZitadelConfig};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
mod auth;
|
|
mod introspection;
|
|
mod oauth;
|
|
mod session;
|
|
|
|
pub use auth::{Auth, AuthService};
|
|
use session::SessionClap;
|
|
pub use session::SessionService;
|
|
|
|
#[derive(clap::ValueEnum, Clone, PartialEq, Eq, Debug)]
|
|
pub enum AuthEngine {
|
|
Noop,
|
|
Zitadel,
|
|
}
|
|
|
|
#[derive(clap::ValueEnum, Clone, PartialEq, Eq, Debug)]
|
|
pub enum SessionBackend {
|
|
InMemory,
|
|
Postgresql,
|
|
}
|
|
|
|
#[derive(clap::Args, Clone, PartialEq, Eq, Debug)]
|
|
pub struct AuthClap {
|
|
#[arg(
|
|
env = "AUTH_ENGINE",
|
|
long = "auth-engine",
|
|
requires_ifs = [
|
|
( "zitadel", "ZitadelClap" )
|
|
],
|
|
default_value = "noop" )
|
|
]
|
|
pub engine: AuthEngine,
|
|
|
|
#[arg(
|
|
env = "SESSION_BACKEND",
|
|
long = "session-backend",
|
|
requires_ifs = [
|
|
( "postgresql", "PostgresqlSessionClap" )
|
|
],
|
|
default_value = "in-memory" )
|
|
]
|
|
pub session_backend: SessionBackend,
|
|
|
|
#[clap(flatten)]
|
|
pub zitadel: ZitadelClap,
|
|
|
|
#[clap(flatten)]
|
|
pub session: SessionClap,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct AuthConfigFile {
|
|
zitadel: Option<ZitadelClap>,
|
|
}
|
|
|
|
#[derive(clap::Args, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[group(requires_all = ["auth_url", "client_id", "client_secret", "redirect_url", "token_url", "authority_url"])]
|
|
pub struct ZitadelClap {
|
|
#[arg(env = "ZITADEL_AUTH_URL", long = "zitadel-auth-url")]
|
|
pub auth_url: Option<String>,
|
|
|
|
#[arg(env = "ZITADEL_CLIENT_ID", long = "zitadel-client-id")]
|
|
pub client_id: Option<String>,
|
|
|
|
#[arg(env = "ZITADEL_CLIENT_SECRET", long = "zitadel-client-secret")]
|
|
pub client_secret: Option<String>,
|
|
|
|
#[arg(env = "ZITADEL_REDIRECT_URL", long = "zitadel-redirect-url")]
|
|
pub redirect_url: Option<String>,
|
|
|
|
#[arg(env = "ZITADEL_AUTHORITY_URL", long = "zitadel-authority-url")]
|
|
pub authority_url: Option<String>,
|
|
|
|
#[arg(env = "ZITADEL_TOKEN_URL", long = "zitadel-token-url")]
|
|
pub token_url: Option<String>,
|
|
}
|
|
|
|
impl TryFrom<AuthClap> for OAuth {
|
|
type Error = anyhow::Error;
|
|
|
|
fn try_from(value: AuthClap) -> Result<Self, Self::Error> {
|
|
match value.engine {
|
|
AuthEngine::Noop => Ok(OAuth::new_noop()),
|
|
AuthEngine::Zitadel => Ok(OAuth::from(ZitadelConfig::try_from(value.zitadel)?)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AuthClap {
|
|
pub fn merge(&mut self, config: AuthConfigFile) -> &mut Self {
|
|
if let Some(zitadel) = config.zitadel {
|
|
if let Some(auth_url) = zitadel.auth_url {
|
|
if let Some(_) = self.zitadel.auth_url {
|
|
_ = self.zitadel.auth_url.replace(auth_url);
|
|
}
|
|
}
|
|
if let Some(client_id) = zitadel.client_id {
|
|
if let Some(_) = self.zitadel.client_id {
|
|
_ = self.zitadel.client_id.replace(client_id);
|
|
}
|
|
}
|
|
if let Some(client_secret) = zitadel.client_secret {
|
|
if let Some(_) = self.zitadel.client_secret {
|
|
_ = self.zitadel.client_secret.replace(client_secret);
|
|
}
|
|
}
|
|
if let Some(redirect_url) = zitadel.redirect_url {
|
|
if let Some(_) = self.zitadel.redirect_url {
|
|
_ = self.zitadel.redirect_url.replace(redirect_url);
|
|
}
|
|
}
|
|
if let Some(authority_url) = zitadel.authority_url {
|
|
if let Some(_) = self.zitadel.authority_url {
|
|
_ = self.zitadel.authority_url.replace(authority_url);
|
|
}
|
|
}
|
|
if let Some(token_url) = zitadel.token_url {
|
|
if let Some(_) = self.zitadel.token_url {
|
|
_ = self.zitadel.token_url.replace(token_url);
|
|
}
|
|
}
|
|
}
|
|
|
|
self
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::{
|
|
session::{PostgresqlSessionClap, SessionClap},
|
|
AuthClap, AuthEngine, SessionBackend, ZitadelClap,
|
|
};
|
|
use clap::Parser;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[derive(Parser)]
|
|
#[command(author, version, about, long_about = None)]
|
|
pub struct Cli {
|
|
#[command(subcommand)]
|
|
command: Commands,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Clone, Debug, Eq, PartialEq)]
|
|
pub enum Commands {
|
|
One {
|
|
#[clap(flatten)]
|
|
options: AuthClap,
|
|
},
|
|
}
|
|
|
|
#[test]
|
|
fn test_command_parse_as_default_noop() {
|
|
let cli: Cli = Cli::parse_from(&["base", "one"]);
|
|
|
|
assert_eq!(
|
|
cli.command,
|
|
Commands::One {
|
|
options: AuthClap {
|
|
engine: AuthEngine::Noop,
|
|
zitadel: ZitadelClap {
|
|
auth_url: None,
|
|
client_id: None,
|
|
client_secret: None,
|
|
redirect_url: None,
|
|
token_url: None,
|
|
authority_url: None,
|
|
},
|
|
session_backend: SessionBackend::InMemory,
|
|
session: SessionClap {
|
|
postgresql: PostgresqlSessionClap { conn: None }
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_command_parse_as_noop() {
|
|
let cli: Cli = Cli::parse_from(&["base", "one", "--auth-engine", "noop"]);
|
|
|
|
assert_eq!(
|
|
cli.command,
|
|
Commands::One {
|
|
options: AuthClap {
|
|
engine: AuthEngine::Noop,
|
|
zitadel: ZitadelClap {
|
|
auth_url: None,
|
|
client_id: None,
|
|
client_secret: None,
|
|
redirect_url: None,
|
|
token_url: None,
|
|
authority_url: None,
|
|
},
|
|
session_backend: crate::SessionBackend::InMemory,
|
|
session: crate::SessionClap {
|
|
postgresql: PostgresqlSessionClap { conn: None }
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_command_parse_as_zitadel() {
|
|
let cli: Cli = Cli::parse_from(&[
|
|
"base",
|
|
"one",
|
|
"--auth-engine=zitadel",
|
|
"--zitadel-client-id=something",
|
|
"--zitadel-client-secret=something",
|
|
"--zitadel-auth-url=https://something",
|
|
"--zitadel-redirect-url=https://something",
|
|
"--zitadel-token-url=https://something",
|
|
"--zitadel-authority-url=https://something",
|
|
]);
|
|
|
|
assert_eq!(
|
|
cli.command,
|
|
Commands::One {
|
|
options: AuthClap {
|
|
engine: AuthEngine::Zitadel,
|
|
zitadel: ZitadelClap {
|
|
auth_url: Some("https://something".into()),
|
|
client_id: Some("something".into()),
|
|
client_secret: Some("something".into()),
|
|
redirect_url: Some("https://something".into()),
|
|
token_url: Some("https://something".into()),
|
|
authority_url: Some("https://something".into()),
|
|
},
|
|
session_backend: crate::SessionBackend::InMemory,
|
|
session: crate::SessionClap {
|
|
postgresql: PostgresqlSessionClap { conn: None }
|
|
}
|
|
},
|
|
}
|
|
);
|
|
}
|
|
}
|