Skip to content

Commit

Permalink
Add token field for exact app matches
Browse files Browse the repository at this point in the history
  • Loading branch information
jameswestman committed Oct 6, 2022
1 parent 8e055d4 commit c1f0287
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
16 changes: 16 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub struct TokenSubsetArgs {
scope: Vec<ClaimsScope>,
duration: i64,
prefixes: Option<Vec<String>>,
apps: Option<Vec<String>>,
repos: Option<Vec<String>>,
name: String,
}
Expand Down Expand Up @@ -135,6 +136,13 @@ pub fn prefix_is_subset(
}
}

pub fn apps_is_subset(maybe_subset_apps: &Option<Vec<String>>, claimed_apps: &[String]) -> bool {
match maybe_subset_apps {
Some(subset_apps) => subset_apps.iter().all(|s| claimed_apps.contains(s)),
None => true,
}
}

pub fn token_subset(
args: Json<TokenSubsetArgs>,
config: Data<Config>,
Expand All @@ -148,6 +156,7 @@ pub fn token_subset(
&& tokens::sub_has_prefix(&args.sub, &claims.sub)
&& args.scope.iter().all(|s| claims.scope.contains(s))
&& prefix_is_subset(&args.prefixes, &claims.prefixes)
&& apps_is_subset(&args.apps, &claims.apps)
&& repos_is_subset(&args.repos, &claims.repos)
{
let new_claims = Claims {
Expand All @@ -161,6 +170,13 @@ pub fn token_subset(
claims.prefixes.clone()
}
},
apps: {
if let Some(ref apps) = args.apps {
apps.clone()
} else {
claims.apps.clone()
}
},
repos: {
if let Some(ref repos) = args.repos {
repos.clone()
Expand Down
3 changes: 2 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,13 @@ pub struct Claims {
pub sub: String, // "build", "build/N", or user id for repo tokens
pub exp: i64,

// Below are optional, and not used for repo tokens
#[serde(default)]
pub scope: Vec<ClaimsScope>,
#[serde(default)]
pub prefixes: Vec<String>, // [''] => all, ['org.foo'] => org.foo + org.foo.bar (but not org.foobar)
#[serde(default)]
pub apps: Vec<String>, // like prefixes, but only exact matches
#[serde(default)]
pub repos: Vec<String>, // list of repo names or a '' for match all
pub name: Option<String>, // for debug/logs only
}
Expand Down
7 changes: 5 additions & 2 deletions src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,14 @@ impl ClaimsValidator for HttpRequest {
/* A token prefix is something like org.my.App, and should allow
* you to create refs like org.my.App, org.my.App.Debug, and
* org.my.App.Some.Long.Thing. However, it should not allow
* org.my.AppSuffix.
* org.my.AppSuffix. Also checks the "apps" field for exact matches
* only.
*/
fn has_token_prefix(&self, id: &str) -> Result<(), ApiError> {
self.validate_claims(|claims| {
if !id_matches_one_prefix(id, &claims.prefixes) {
if !id_matches_one_prefix(id, &claims.prefixes)
&& !claims.apps.contains(&id.to_string())
{
return Err(ApiError::NotEnoughPermissions(format!(
"Id {} not matching prefix in token",
id
Expand Down

0 comments on commit c1f0287

Please sign in to comment.