Delete user from lldap on cleanup

This commit is contained in:
Dreaded_X 2025-03-18 01:22:20 +01:00
parent 87a4749471
commit e858baaa3c
Signed by: Dreaded_X
GPG Key ID: FA5F485356B0D2D4
3 changed files with 60 additions and 5 deletions

View File

@ -39,6 +39,10 @@ pub trait ControllerEvents {
async fn user_created<T>(&self, obj: &T, username: &str) -> Result<(), Self::Error> async fn user_created<T>(&self, obj: &T, username: &str) -> Result<(), Self::Error>
where where
T: Resource<DynamicType = ()> + Sync; T: Resource<DynamicType = ()> + Sync;
async fn user_deleted<T>(&self, obj: &T, username: &str) -> Result<(), Self::Error>
where
T: Resource<DynamicType = ()> + Sync;
} }
#[async_trait] #[async_trait]
@ -78,4 +82,21 @@ impl ControllerEvents for Recorder {
) )
.await .await
} }
async fn user_deleted<T>(&self, obj: &T, username: &str) -> Result<(), Self::Error>
where
T: Resource<DynamicType = ()> + Sync,
{
self.publish(
&Event {
type_: EventType::Normal,
reason: "UserDeleted".into(),
note: Some(format!("Deleted user '{username}'")),
action: "UserDeleted".into(),
secondary: None,
},
&obj.object_ref(&()),
)
.await
}
} }

View File

@ -9,7 +9,7 @@ use tracing::debug;
use cynic::http::{CynicReqwestError, ReqwestExt}; use cynic::http::{CynicReqwestError, ReqwestExt};
use cynic::{GraphQlError, GraphQlResponse, MutationBuilder, QueryBuilder}; use cynic::{GraphQlError, GraphQlResponse, MutationBuilder, QueryBuilder};
use lldap_auth::login::{ClientSimpleLoginRequest, ServerLoginResponse}; use lldap_auth::login::{ClientSimpleLoginRequest, ServerLoginResponse};
use queries::{CreateUser, CreateUserVariables, ListUsers}; use queries::{CreateUser, CreateUserVariables, DeleteUser, DeleteUserVariables, ListUsers};
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Error { pub enum Error {
@ -116,7 +116,18 @@ impl LldapClient {
pub async fn create_user(&self, username: &str) -> Result<()> { pub async fn create_user(&self, username: &str) -> Result<()> {
let operation = CreateUser::build(CreateUserVariables { id: username }); let operation = CreateUser::build(CreateUserVariables { id: username });
// TODO: Check the response? let response = self
.client
.post(format!("{}/api/graphql", self.url))
.run_graphql(operation)
.await?;
check_graphql_errors(&response)
}
pub async fn delete_user(&self, username: &str) -> Result<()> {
let operation = DeleteUser::build(DeleteUserVariables { id: username });
let response = self let response = self
.client .client
.post(format!("{}/api/graphql", self.url)) .post(format!("{}/api/graphql", self.url))

View File

@ -132,6 +132,10 @@ where
) )
} }
fn format_username(name: &str, namespace: &str) -> String {
format!("{name}.{namespace}")
}
#[async_trait] #[async_trait]
impl Reconcile for ServiceUser { impl Reconcile for ServiceUser {
async fn reconcile(self: Arc<Self>, ctx: Arc<Context>) -> Result<Action> { async fn reconcile(self: Arc<Self>, ctx: Arc<Context>) -> Result<Action> {
@ -152,7 +156,7 @@ impl Reconcile for ServiceUser {
debug!(name, "Apply"); debug!(name, "Apply");
let secret_name = format!("{name}-lldap-credentials"); let secret_name = format!("{name}-lldap-credentials");
let username = format!("{name}.{namespace}"); let username = format_username(&name, &namespace);
let client = &ctx.client; let client = &ctx.client;
let secrets = Api::<Secret>::namespaced(client.clone(), &namespace); let secrets = Api::<Secret>::namespaced(client.clone(), &namespace);
@ -221,8 +225,27 @@ impl Reconcile for ServiceUser {
Ok(Action::requeue(Duration::from_secs(3600))) Ok(Action::requeue(Duration::from_secs(3600)))
} }
async fn cleanup(self: Arc<Self>, _ctx: Arc<Context>) -> Result<Action> { async fn cleanup(self: Arc<Self>, ctx: Arc<Context>) -> Result<Action> {
debug!(name = self.name_any(), "Cleanup"); let name = self
.metadata
.name
.clone()
.ok_or(Error::MissingObjectKey(".metadata.name"))?;
let namespace = self
.metadata
.namespace
.clone()
.ok_or(Error::MissingObjectKey(".metadata.namespace"))?;
debug!(name, "Cleanup");
let username = format_username(&name, &namespace);
let lldap_client = ctx.lldap_config.build_client().await?;
trace!(name, username, "Deleting user");
lldap_client.delete_user(&username).await?;
ctx.recorder.user_deleted(self.as_ref(), &username).await?;
Ok(Action::await_change()) Ok(Action::await_change())
} }