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
5 changes: 5 additions & 0 deletions nexus/src/authz/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use super::roles::RoleSet;
use crate::authn;
use crate::authz::SiloUser;
use omicron_common::api::external::LookupType;
use omicron_common::api::external::ResourceType;
use uuid::Uuid;
Expand Down Expand Up @@ -90,5 +91,9 @@ impl oso::PolarClass for AuthenticatedActor {
)
})
})
.add_method(
"equals_silo_user",
|a: &AuthenticatedActor, u: SiloUser| a.actor_id == u.id(),
)
}
}
18 changes: 14 additions & 4 deletions nexus/src/authz/omicron.polar
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,17 @@ has_relation(fleet: Fleet, "parent_fleet", silo: Silo)
#
# It's unclear what else would break if users couldn't see their own Silo.
has_permission(actor: AuthenticatedActor, "read", silo: Silo)
# TODO-security TODO-coverage We should have a test that exercises this
# syntax.
# TODO actor.silo is *not* a list, so `in` is incorrect here, but if you
# replace that with `=` it fails! test_silo_read_for_unpriv covers this
# statement
if silo in actor.silo;

# Any authenticated user should be allowed to list the identity providers of
# their silo.
has_permission(actor: AuthenticatedActor, "list_identity_providers", silo: Silo)
# TODO-security TODO-coverage We should have a test that exercises this
# syntax.
# TODO actor.silo is *not* a list, so `in` is incorrect here, but if you
# replace that with `=` it fails! test_list_silo_idps_for_unpriv covers
# this statement
if silo in actor.silo;

resource Organization {
Expand Down Expand Up @@ -249,6 +251,10 @@ resource SiloUser {
has_relation(silo: Silo, "parent_silo", user: SiloUser)
if user.silo = silo;

# authenticated actors have all permissions on themselves
has_permission(actor: AuthenticatedActor, _perm: String, silo_user: SiloUser)
if actor.equals_silo_user(silo_user);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there any reason not to just do something like actor.id = silo_user.id?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, we can't make UUIDs into Polar classes, since we don't own the crate.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think they're already supported:
https://docs.osohq.com/rust/reference/polar/classes.html#uuids-via-the-uuid-crate

I'll take a swing at this in a follow-up PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The other problem here is that there's no id attribute on silo_user. We could add one, but this type is generated by the authz_resource! macro so either we'd have to make that configurable or everything would get a new id attribute. I decided this isn't worth spending more time on.


resource SshKey {
permissions = [ "read", "modify" ];
relations = { silo_user: SiloUser };
Expand Down Expand Up @@ -346,6 +352,10 @@ resource GlobalImageList {
has_relation(fleet: Fleet, "parent_fleet", global_image_list: GlobalImageList)
if global_image_list.fleet = fleet;

# Any authenticated user can list and read global images
has_permission(_actor: AuthenticatedActor, "list_children", _global_image_list: GlobalImageList);
has_permission(_actor: AuthenticatedActor, "read", _global_image: GlobalImage);

# Describes the policy for creating and managing web console sessions.
resource ConsoleSessionList {
permissions = [ "create_child" ];
Expand Down
Loading