Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion central/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ shared = { workspace = true }
serde = { workspace = true }
futures = { workspace = true }
serde_json = "1"
rand = "0.9"
reqwest = { version = "0.12", default_features = false, features = ["default-tls"] }
anyhow = { workspace = true }
tracing = { workspace = true }
Expand Down
43 changes: 9 additions & 34 deletions central/src/auth/authentik/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ mod group;
mod provider;
mod test;

use crate::auth::generate_secret;
use std::sync::Mutex;
use crate::CLIENT;
use anyhow::bail;
use app::{check_app_result, compare_app_provider, get_application};
use beam_lib::reqwest::{self, Url};
use clap::Parser;
use group::create_groups;
use provider::{compare_provider, generate_provider_values, get_provider, get_provider_id};
use reqwest::StatusCode;
use provider::{compare_provider, generate_provider_values, get_provider};
use reqwest::{Response, StatusCode};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use shared::{OIDCConfig, SecretResult};
use tracing::{debug, info};
use crate::auth::authentik::provider::check_set_federation_id;
use crate::auth::authentik::provider::{check_set_federation_id, generate_provider, update_provider};

#[derive(Debug, Parser, Clone)]
pub struct AuthentikConfig {
Expand Down Expand Up @@ -99,38 +98,21 @@ pub async fn create_app_provider(
name: &str,
oidc_client_config: &OIDCConfig,
conf: &AuthentikConfig,
) -> anyhow::Result<SecretResult> {
combine_app_provider(name, oidc_client_config, conf).await
}

pub async fn combine_app_provider(
name: &str,
oidc_client_config: &OIDCConfig,
conf: &AuthentikConfig,
) -> anyhow::Result<SecretResult> {
let client_id = oidc_client_config.client_type(name);
let secret = if !oidc_client_config.is_public {
generate_secret()
} else {
String::with_capacity(0)
};
let generated_provider =
let secret = oidc_client_config.secret_type();
let generated_provider: Value =
generate_provider_values(&client_id, oidc_client_config, &secret, conf).await?;
debug!("Provider Values: {:#?}", generated_provider);
let provider_res = CLIENT
.post(conf.authentik_url.join("api/v3/providers/oauth2/")?)
.bearer_auth(&conf.authentik_service_api_key)
.json(&generated_provider)
.send()
.await?;
let provider_res: Response = generate_provider(&generated_provider, conf).await?;
// Create groups for this client
create_groups(name, conf).await?;
debug!("Result Provider: {:#?}", provider_res);
match provider_res.status() {
StatusCode::CREATED => {
let res_provider: serde_json::Value = provider_res.json().await?;
let provider_id = res_provider.get("pk").and_then(|v| v.as_i64()).unwrap();
let provider_name = res_provider.get("name").and_then(|v| v.as_str()).unwrap();
let provider_id = res_provider["pk"].as_i64().expect("provider_id have to be present");
let provider_name = res_provider["name"].as_str().expect("provider_name have to be present");
// check and set federation_id
check_set_federation_id(&name, provider_id, conf, oidc_client_config).await?;
debug!("{:?}", provider_id);
Expand Down Expand Up @@ -180,14 +162,7 @@ pub async fn combine_app_provider(
);
}
} else {
let res = CLIENT
.patch(conf.authentik_url.join(&format!(
"api/v3/providers/oauth2/{}/",
get_provider_id(&client_id, conf).await.unwrap()
))?)
.bearer_auth(&conf.authentik_service_api_key)
.json(&generated_provider)
.send()
let res = update_provider(&generated_provider, &client_id, conf)
.await?
.status()
.is_success()
Expand Down
33 changes: 33 additions & 0 deletions central/src/auth/authentik/provider.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::{Context, Ok};
use reqwest::Response;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use shared::OIDCConfig;
Expand Down Expand Up @@ -63,6 +64,38 @@ pub async fn generate_provider_values(
Ok(json)
}

pub async fn generate_provider(
generated_provider: &Value,
conf: &AuthentikConfig,
) -> anyhow::Result<Response> {
Ok(
CLIENT
.post(conf.authentik_url.join("api/v3/providers/oauth2/")?)
.bearer_auth(&conf.authentik_service_api_key)
.json(generated_provider)
.send()
.await?
)
}

pub async fn update_provider(
provider_values: &Value,
client_id: &str,
conf: &AuthentikConfig,
) -> anyhow::Result<Response> {
Ok(
CLIENT
.patch(conf.authentik_url.join(&format!(
"api/v3/providers/oauth2/{}/",
get_provider_id(&client_id, conf).await.expect("provider id have to be present")
))?)
.bearer_auth(&conf.authentik_service_api_key)
.json(provider_values)
.send()
.await?
)
}

pub async fn get_provider_id(
client_id: &str,
conf: &AuthentikConfig
Expand Down
9 changes: 4 additions & 5 deletions central/src/auth/authentik/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
#[allow(unused_imports)]
use crate::auth::authentik::app::{check_app_result, compare_app_provider, generate_app_values};
use crate::auth::authentik::group::{create_groups, post_group};
use crate::auth::authentik::provider::{generate_provider_values, get_provider, get_provider_id};
use crate::auth::authentik::{
combine_app_provider, get_application, get_uuid, validate_application, AuthentikConfig,
};
use crate::auth::authentik::{create_app_provider, get_application, get_uuid, validate_application, AuthentikConfig};
use crate::CLIENT;
use beam_lib::reqwest::{self, Error, StatusCode, Url};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -57,7 +56,7 @@ async fn test_create_client() -> anyhow::Result<()> {
],
};
let (SecretResult::Created(pw) | SecretResult::AlreadyExisted(pw)) =
dbg!(combine_app_provider(name, &client_config, &conf).await?)
dbg!(create_app_provider(name, &client_config, &conf).await?)
else {
panic!("Not created or existed")
};
Expand All @@ -81,7 +80,7 @@ async fn test_create_client() -> anyhow::Result<()> {
],
};
let (SecretResult::Created(pw) | SecretResult::AlreadyExisted(pw)) =
dbg!(combine_app_provider(name, &client_config, &conf).await?)
dbg!(create_app_provider(name, &client_config, &conf).await?)
else {
panic!("Not created or existed")
};
Expand Down
10 changes: 3 additions & 7 deletions central/src/auth/keycloak/client.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{
auth::{generate_secret, keycloak::add_service_account_roles},
auth::{keycloak::add_service_account_roles},
CLIENT,
};
use anyhow::bail;
use beam_lib::reqwest::{self, StatusCode};
use serde_json::{json, Value};
use shared::{OIDCConfig, SecretResult};
use shared::{generate_secret, OIDCConfig, SecretResult};

use super::{create_groups, KeyCloakConfig};

Expand Down Expand Up @@ -120,11 +120,7 @@ pub async fn post_client(
oidc_client_config: &OIDCConfig,
conf: &KeyCloakConfig,
) -> anyhow::Result<SecretResult> {
let secret = if !oidc_client_config.is_public {
generate_secret()
} else {
String::with_capacity(0)
};
let secret = oidc_client_config.secret_type();
let generated_client = generate_client(name, oidc_client_config, &secret);
let res = CLIENT
.post(&format!(
Expand Down
1 change: 1 addition & 0 deletions central/src/auth/keycloak/test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[allow(unused_imports)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? You should probably add a #[cfg(test)] above the mod tests; in mod.rs which might solve some of your import issues

use crate::auth::keycloak::client::{
client_configs_match, compare_clients, generate_client, get_client, post_client,
};
Expand Down
15 changes: 0 additions & 15 deletions central/src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
pub mod authentik;
pub mod keycloak;

pub fn generate_secret() -> String {
use rand::Rng;
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
const PASSWORD_LEN: usize = 30;
let mut rng = rand::thread_rng();

(0..PASSWORD_LEN)
.map(|_| {
let idx = rng.gen_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect()
}
1 change: 1 addition & 0 deletions shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ license = "Apache-2.0"

[dependencies]
serde = { workspace = true }
rand = "0.9.1"
23 changes: 23 additions & 0 deletions shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ impl OIDCConfig {
pub fn client_type(&self, name: &str) -> String {
format!("{}-{}", name, if self.is_public { "public" } else { "private" })
}
pub fn secret_type(&self) -> String {
if !self.is_public {
generate_secret()
} else {
String::with_capacity(0)
}
}
//use case federation id
pub fn flipped_client_type(&self, name: &str) -> String {
format!("{}-{}", name, if self.is_public { "private" } else { "public" })
Expand Down Expand Up @@ -45,3 +52,19 @@ pub struct SecretRequest {
pub request_type: RequestType,
pub secret_type: SecretType,
}

pub fn generate_secret() -> String {
use rand::Rng;
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
const PASSWORD_LEN: usize = 30;
let mut rng = rand::rng();

(0..PASSWORD_LEN)
.map(|_| {
let idx = rng.random_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect()
}