Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(permission): support suffix wildcards in --allow-env flag #25255

Conversation

yazan-abdalrahman
Copy link
Contributor

@yazan-abdalrahman yazan-abdalrahman changed the title feat(permission): Add wildcard support to --allow-env flag for environment variable pat… feat(permission): Enhance --allow-env to Support Prefix, Suffix Wildcard Matching Aug 28, 2024
@yazan-abdalrahman
Copy link
Contributor Author

yazan-abdalrahman commented Aug 28, 2024

Could @lucacasonato @dsherret @bartlomieju Pls review the change?

…refix,-Suffix,-and-Wildcard-Matching' into Enhance---allow-env-to-Support-Prefix,-Suffix,-and-Wildcard-Matching
Copy link
Member

@lucacasonato lucacasonato left a comment

Choose a reason for hiding this comment

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

I don't think this works. If you do --allow-env=FOOBAR_* and then try to do Deno.env.set("FOOBAR_X", "1"), it would not be allowed even though FOOBAR_* was passed as a permission, because FOOBAR_X was not present when the script started up.

@yazan-abdalrahman
Copy link
Contributor Author

yazan-abdalrahman commented Aug 29, 2024

I don't think this works. If you do --allow-env=FOOBAR_* and then try to do Deno.env.set("FOOBAR_X", "1"), it would not be allowed even though FOOBAR_* was passed as a permission, because FOOBAR_X was not present when the script started up.

@lucacasonato
I think so, but the permissions it should granted before starting the script, so any new permissions will prompt the user for permission.

This edge case requires separate tickets. Maybe we need to verify permission before prompt, and if we have a wildcard, we need to change the permission_list  or  u can use --allow-env for this case because checking permission list if it has wildcard then update list linked to it that makes more effort on deno and makes it slower.

@yazan-abdalrahman
Copy link
Contributor Author

@lucacasonato
please review the latest commit and modifications for a new solution that supports setting and getting environments variables.
image

Comment on lines 2345 to 2373
static WILDCARD_PERMISSIONS: Lazy<RwLock<Vec<String>>> =
Lazy::new(|| RwLock::new(Vec::new()));

pub fn add_wildcard_permission(permission: &str) -> Result<(), String> {
let mut permissions = WILDCARD_PERMISSIONS.write().map_err(|e| {
error!("Failed to acquire write lock: {}", e);
"Failed to add wildcard permission".to_string()
})?;
if !permissions.contains(&permission.to_string()) {
permissions.push(permission.to_string());
}
Ok(())
}

pub fn get_wildcard_permissions() -> Vec<String> {
let permissions = WILDCARD_PERMISSIONS
.read()
.expect("Failed to acquire read lock");
permissions.clone()
}

pub fn clear_wildcard_permissions() -> Result<(), String> {
let mut permissions = WILDCARD_PERMISSIONS.write().map_err(|e| {
error!("Failed to acquire write lock: {}", e);
"Failed to clear wildcard permissions".to_string()
})?;
permissions.clear();
Ok(())
}
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain the purpose of this code? What's the reason for having a static with a lock just to match permissions?

Copy link
Contributor Author

@yazan-abdalrahman yazan-abdalrahman Sep 5, 2024

Choose a reason for hiding this comment

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

@bartlomieju

The code uses a RwLock to handle wildcard permissions dynamically. When a wildcard is passed (e.g., --allow-env=MYAPP_*), the logic captures and stores these patterns. Before checking an environment variable's permission, the stored patterns are matched to grant access. The lock ensures thread-safe reads/writes while allowing concurrent reads. This dynamic approach helps manage permissions for env variables set by the user (via Deno.env.set), even if they weren’t present at the script’s start. It addresses the issue where wildcard permissions don’t automatically allow newly set env variables like FOOBAR_X

Copy link
Member

Choose a reason for hiding this comment

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

That is not correct. You want to solve the same way --allow-net permissions are stored - you store an enum of either a concrete value (--allow-env=NODE_DEBUG) or a wildcard match (--allow-env=AWS_*, --allow-env=*_DENO). Then when the permission is checked you either perform an exact match on "concrete value" enum variant, or a wildcard match on the other variant. The RwLock is not needed in here.

So you need to update EnvDescriptor to something like:

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum EnvDescriptor {
  Concrete(EnvVarName),
  Wildcard(...)
}

and then impl UnaryPermission<EnvDescriptor> to apply that logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@bartlomieju ,
its cant be Enum maybe have many suffixes like this AWS_,FOOBAR_ , many prefix *_DENO, *_EXALT,
how theses random different name can be stores in Enum

Copy link
Member

Choose a reason for hiding this comment

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

You store one element in a single enum - then multiple enums are stored here:

pub struct UnaryPermission<T: Descriptor + Hash> {
granted_global: bool,
granted_list: HashSet<T>,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You store one element in a single enum - then multiple enums are stored here:

pub struct UnaryPermission<T: Descriptor + Hash> {
granted_global: bool,
granted_list: HashSet<T>,

@bartlomieju
done check latest commit

Comment on lines 4958 to 4959
for env_var in &env_permissions {
if env_var.contains('*') {
Copy link
Member

Choose a reason for hiding this comment

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

--allow-env=* makes no sense because it's equal to --allow-env. If we are to support "wildcards" in env var names it should only be at the begging or end (AWS_*, *_DENO)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK I will remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

--allow-env=* makes no sense because it's equal to --allow-env. If we are to support "wildcards" in env var names it should only be at the begging or end (AWS_*, *_DENO)

done

…refix,-Suffix,-and-Wildcard-Matching' into Enhance---allow-env-to-Support-Prefix,-Suffix,-and-Wildcard-Matching
@yazan-abdalrahman
Copy link
Contributor Author

@lucacasonato @bartlomieju
please check it again

@yazan-abdalrahman
Copy link
Contributor Author

@bartlomieju

@yazan-abdalrahman
Copy link
Contributor Author

@dsherret
please review this

@yazan-abdalrahman
Copy link
Contributor Author

Please review this change.

@yazan-abdalrahman
Copy link
Contributor Author

Please review this change.

@bartlomieju bartlomieju added this to the 2.1.0 milestone Nov 1, 2024
@yazan-abdalrahman
Copy link
Contributor Author

@dsherret Please review this change.

Copy link
Member

@dsherret dsherret left a comment

Choose a reason for hiding this comment

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

What happens when someone queries for if permisisons are allowed via the Deno.permissions.query API? It seems like this wouldn't handle that?

I feel like probably we should introduce an EnvQueryDescriptor on EnvDescriptor's AllowDesc that could be an explicit name or pattern, then we could compare EnvDescriptor to it.

@bartlomieju bartlomieju changed the title feat(permission): Enhance --allow-env to Support Prefix, Suffix Wildcard Matching feat(permission): support suffix wildcards in --allow-env flag Nov 17, 2024
Comment on lines 1207 to 1222
match other {
Self::AllowDesc::Name(n) => match &self.0 {
EnvQueryDescriptorInner::Name(env_var_name) => n == env_var_name,
EnvQueryDescriptorInner::PrefixPattern(env_var_name) => {
env_var_name.as_ref().starts_with(n.as_ref())
}
},
Self::AllowDesc::PrefixPattern(p) => match &self.0 {
EnvQueryDescriptorInner::Name(env_var_name) => {
env_var_name.as_ref().starts_with(p.as_ref())
}
EnvQueryDescriptorInner::PrefixPattern(env_var_name) => {
p == env_var_name
}
},
}
Copy link
Member

Choose a reason for hiding this comment

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

Review this one thoroughly

Copy link
Member

Choose a reason for hiding this comment

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

I updated it (see the new test)

Copy link
Member

@dsherret dsherret left a comment

Choose a reason for hiding this comment

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

LGTM

@bartlomieju bartlomieju enabled auto-merge (squash) November 20, 2024 22:22
@bartlomieju bartlomieju merged commit b729bf0 into denoland:main Nov 20, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants