[pdm-devel] [PATCH datacenter-manager 3/3] server: clean up acl tree entries and api tokens when deleting users
Fabian Grünbichler
f.gruenbichler at proxmox.com
Thu Oct 2 12:19:47 CEST 2025
On October 1, 2025 5:29 pm, Shannon Sterz wrote:
> On Fri Sep 26, 2025 at 11:18 AM CEST, Fabian Grünbichler wrote:
>> On September 24, 2025 4:51 pm, Shannon Sterz wrote:
>>> Signed-off-by: Shannon Sterz <s.sterz at proxmox.com>
>>> ---
>>> server/src/api/access/users.rs | 39 +++++++++++++++++++++++++++++-----
>>> 1 file changed, 34 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/server/src/api/access/users.rs b/server/src/api/access/users.rs
>>> index da598d8..1d1accb 100644
>>> --- a/server/src/api/access/users.rs
>>> +++ b/server/src/api/access/users.rs
>>> @@ -334,20 +334,19 @@ pub fn update_user(
>>> /// Remove a user from the configuration file.
>>> pub fn delete_user(userid: Userid, digest: Option<ConfigDigest>) -> Result<(), Error> {
>>> let _lock = proxmox_access_control::user::lock_config()?;
>>> + let _acl_lock = proxmox_access_control::acl::lock_config()?;
>>> let _tfa_lock = crate::auth::tfa::write_lock()?;
>>>
>>> - let (mut config, config_digest) = proxmox_access_control::user::config()?;
>>> + let (mut user_config, config_digest) = proxmox_access_control::user::config()?;
>>> config_digest.detect_modification(digest.as_ref())?;
>>>
>>> - match config.sections.get(userid.as_str()) {
>>> + match user_config.sections.get(userid.as_str()) {
>>> Some(_) => {
>>> - config.sections.remove(userid.as_str());
>>> + user_config.sections.remove(userid.as_str());
>>> }
>>> None => bail!("user '{}' does not exist.", userid),
>>> }
>>>
>>> - proxmox_access_control::user::save_config(&config)?;
>>> -
>>> let authenticator = crate::auth::lookup_authenticator(userid.realm())?;
>>> match authenticator.remove_password(userid.name()) {
>>> Ok(()) => {}
>>> @@ -375,6 +374,36 @@ pub fn delete_user(userid: Userid, digest: Option<ConfigDigest>) -> Result<(), E
>>> }
>>> }
>>>
>>> + let user_tokens: Vec<ApiToken> = user_config
>>> + .convert_to_typed_array::<ApiToken>("token")?
>>> + .into_iter()
>>> + .filter(|token| token.tokenid.user().eq(&userid))
>>> + .collect();
>>
>> do we have any consistency checks between ACLs and users/tokens? if not,
>> then..
>>
>>> +
>>> + let (mut acl_config, _digest) = proxmox_access_control::acl::config()?;
>>> +
>>> + let auth_id = userid.clone().into();
>>> + acl_config.delete_authid(&auth_id);
>>> +
>>> + for token in user_tokens {
>>> + if let Some(token_name) = token.tokenid.tokenname() {
>>> + let tokenid = Authid::from((userid.clone(), Some(token_name.to_owned())));
>>> + let tokenid_string = tokenid.to_string();
>>> + if user_config.sections.remove(&tokenid_string).is_none() {
>>> + bail!(
>>> + "token '{}' of user '{userid}' does not exist.",
>>> + token_name.as_str()
>>> + );
>>> + }
>>> +
>>> + proxmox_access_control::token_shadow::delete_secret(&tokenid)?;
>>> + acl_config.delete_authid(&tokenid);
>>
>> this is not enough to remove all ACLs, since removing a token via the
>> token API currently does not clean up its ACL entries..
>
> i added the clean up for tokens in a v2.
>
> but im not entirely sure if i understand you here correctly. are you
> worried about token acls not getting cleaned up if only the token is
> deleted? because then yeah, that part was missing as you pointed out
> there correctly. or is there another scenario you have in mind that i
> currently don't see?
no, that was exactly the issue I was worried about!
delete token => ACL remains
delete user => token doesn't exist, so ACL is not removed either here
in PVE we just drop ACLs on parsing that reference invalid authids..
More information about the pdm-devel
mailing list