Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion policy/federation/idp/identity_provider_list.rego
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ default allow := false

default can_see_other_domain_resources := false

can_see_other_domain_resources := true if {
can_see_other_domain_resources if {
"admin" in input.credentials.roles
}

Expand Down
10 changes: 10 additions & 0 deletions policy/identity.rego
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,13 @@ foreign_mapping if {
input.target.domain_id != null
input.target.domain_id != input.credentials.domain_id
}

foreign_token_restriction if {
input.target.domain_id != null
input.target.domain_id != input.credentials.domain_id
}

own_token_restriction if {
input.target.domain_id != null
input.target.domain_id == input.credentials.domain_id
}
27 changes: 27 additions & 0 deletions policy/token/restriction/create.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package identity.token_restriction.create

import data.identity

# Create token restriction.

default allow := false

allow if {
"admin" in input.credentials.roles
}

allow if {
"manager" in input.credentials.roles
identity.own_token_restriction
}

allow if {
"member" in input.credentials.roles
input.target.user_id != null
input.credentials.user_id == input.target.user_id
}

violation contains {"field": "domain_id", "msg": "creating token restrictions in other domain requires `admin` role."} if {
identity.foreign_token_restriction
not "admin" in input.credentials.roles
}
19 changes: 19 additions & 0 deletions policy/token/restriction/create_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package test_token_restriction_create

import data.identity.token_restriction.create

test_allowed if {
create.allow with input as {"credentials": {"roles": ["admin"]}}
create.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "domain"}}
create.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
create.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
create.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
}

test_forbidden if {
not create.allow with input as {"credentials": {"roles": []}}
not create.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not create.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not create.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not create.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid1"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
}
27 changes: 27 additions & 0 deletions policy/token/restriction/delete.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package identity.token_restriction.delete

import data.identity

# Delete token restriction.

default allow := false

allow if {
"admin" in input.credentials.roles
}

allow if {
"manager" in input.credentials.roles
identity.own_token_restriction
}

allow if {
"member" in input.credentials.roles
input.target.user_id != null
input.credentials.user_id == input.target.user_id
}

violation contains {"field": "domain_id", "msg": "deleting token restrictions in other domain requires `admin` role."} if {
identity.foreign_token_restriction
not "admin" in input.credentials.roles
}
19 changes: 19 additions & 0 deletions policy/token/restriction/delete_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package test_token_restriction_delete

import data.identity.token_restriction.delete

test_allowed if {
delete.allow with input as {"credentials": {"roles": ["admin"]}}
delete.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "domain"}}
delete.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
delete.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
delete.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
}

test_forbidden if {
not delete.allow with input as {"credentials": {"roles": []}}
not delete.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not delete.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not delete.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not delete.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid1"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
}
25 changes: 25 additions & 0 deletions policy/token/restriction/list.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package identity.token_restriction.list

import data.identity

# List token restriction.

default allow := false

allow if {
"admin" in input.credentials.roles
}

allow if {
"manager" in input.credentials.roles
}

allow if {
"member" in input.credentials.roles
identity.own_token_restriction
}

violation contains {"field": "domain_id", "msg": "showing token restrictions requires `admin` role."} if {
identity.foreign_token_restriction
not "admin" in input.credentials.roles
}
15 changes: 15 additions & 0 deletions policy/token/restriction/list_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package test_token_restriction_list

import data.identity.token_restriction.list

test_allowed if {
list.allow with input as {"credentials": {"roles": ["admin"]}}
list.allow with input as {"credentials": {"roles": ["manager"]}}
list.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "domain"}}
}

test_forbidden if {
not list.allow with input as {"credentials": {"roles": []}}
not list.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not list.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
}
17 changes: 4 additions & 13 deletions policy/token/restriction/show.rego
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package identity.token_restriction_show
package identity.token_restriction.show

import data.identity

# Create mapping.
# Show single token restriction.

default allow := false

Expand All @@ -11,20 +11,11 @@ allow if {
}

allow if {
identity.own_token_restriction
"manager" in input.credentials.roles
}

violation contains {"field": "domain_id", "msg": "showing token restrictions requires `admin` role."} if {
#identity.foreign_mapping
identity.foreign_token_restriction
not "admin" in input.credentials.roles
}

#violation contains {"field": "role", "msg": "creating global mapping requires `admin` role."} if {
# identity.global_mapping
# not "admin" in input.credentials.roles
#}
#
#violation contains {"field": "role", "msg": "creating mapping requires `manager` role."} if {
# identity.own_mapping
# not "member" in input.credentials.roles
#}
10 changes: 5 additions & 5 deletions policy/token/restriction/show_test.rego
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package test_token_restriction_show

import data.identity.token_restriction_show
import data.identity.token_restriction.show

test_allowed if {
token_restriction_show.allow with input as {"credentials": {"roles": ["admin"]}}
show.allow with input as {"credentials": {"roles": ["admin"]}}
#token_restriction_show.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "domain"}}
#token_restriction_show.allow with input as {"credentials": {"roles": ["reader"]}, "target": {"domain_id": null}}
}

test_forbidden if {
not token_restriction_show.allow with input as {"credentials": {"roles": []}}
not token_restriction_show.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not token_restriction_show.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not show.allow with input as {"credentials": {"roles": []}}
not show.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not show.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
}
27 changes: 27 additions & 0 deletions policy/token/restriction/update.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package identity.token_restriction.update

import data.identity

# Update token restriction.

default allow := false

allow if {
"admin" in input.credentials.roles
}

allow if {
"manager" in input.credentials.roles
identity.own_token_restriction
}

allow if {
"member" in input.credentials.roles
input.target.user_id != null
input.credentials.user_id == input.target.user_id
}

violation contains {"field": "domain_id", "msg": "updating token restrictions in other domain requires `admin` role."} if {
identity.foreign_token_restriction
not "admin" in input.credentials.roles
}
19 changes: 19 additions & 0 deletions policy/token/restriction/update_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package test_token_restriction_update

import data.identity.token_restriction.update

test_allowed if {
update.allow with input as {"credentials": {"roles": ["admin"]}}
update.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "domain"}}
update.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
update.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
update.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid"}, "target": {"domain_id": "domain", "user_id": "uid"}}
}

test_forbidden if {
not update.allow with input as {"credentials": {"roles": []}}
not update.allow with input as {"credentials": {"roles": ["reader"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not update.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not update.allow with input as {"credentials": {"roles": ["manager"], "domain_id": "domain"}, "target": {"domain_id": "other_domain"}}
not update.allow with input as {"credentials": {"roles": ["member"], "domain_id": "domain", "user_id": "uid1"}, "target": {"domain_id": "domain", "user_id": "uid2"}}
}
9 changes: 9 additions & 0 deletions src/api/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ impl KeystoneApiError {
_ => source.into(),
}
}
pub fn token(source: TokenProviderError) -> Self {
match source {
TokenProviderError::TokenRestrictionNotFound(x) => Self::NotFound {
resource: "token restriction".into(),
identifier: x,
},
_ => source.into(),
}
}
}

#[derive(Debug, Error)]
Expand Down
16 changes: 1 addition & 15 deletions src/api/v4/federation/identity_provider/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,21 +229,7 @@ mod tests {
#[tokio::test]
#[traced_test]
async fn test_list_forbidden() {
let mut federation_mock = MockFederationProvider::default();
federation_mock
.expect_list_identity_providers()
.withf(
|_: &DatabaseConnection, _: &provider_types::IdentityProviderListParameters| true,
)
.returning(|_, _| {
Ok(vec![provider_types::IdentityProvider {
id: "id".into(),
name: "name".into(),
domain_id: Some("did".into()),
default_mapping_name: Some("dummy".into()),
..Default::default()
}])
});
let federation_mock = MockFederationProvider::default();
let state = get_mocked_state(federation_mock, false, None);

let mut api = openapi_router()
Expand Down
10 changes: 8 additions & 2 deletions src/api/v4/token/restriction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ Token restrictions allow controlling multiple aspects of the authentication and
- `roles` binds the roles of the issued token on the scope. Using this bypasses necessity to grant the roles explicitly to the user.
"#;

mod create;
mod delete;
mod list;
mod show;
mod update;

pub(super) fn openapi_router() -> OpenApiRouter<ServiceState> {
OpenApiRouter::new().routes(routes!(show::show))
OpenApiRouter::new()
.routes(routes!(show::show, delete::remove, update::update))
.routes(routes!(list::list, create::create))
}

#[cfg(test)]
Expand All @@ -45,7 +51,7 @@ mod tests {
use std::sync::Arc;

use crate::config::Config;
use crate::federation::MockFederationProvider;

use crate::identity::types::UserResponse;
use crate::keystone::{Service, ServiceState};
use crate::policy::{MockPolicy, MockPolicyFactory, PolicyError, PolicyEvaluationResult};
Expand Down
Loading
Loading