Skip to content
Open
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
96 changes: 53 additions & 43 deletions nexus/auth/src/authz/omicron.polar
Original file line number Diff line number Diff line change
Expand Up @@ -40,45 +40,62 @@ has_role(actor: AuthenticatedActor, role: String, resource: Resource)
# - "read": required to read a resource
#
# We define the following predefined roles for only a few high-level resources:
# the Fleet (see below), Silo, Organization, and Project. The specific roles
# are oriented around intended use-cases:
# the Fleet (see below), Silo, and Project. The specific roles are oriented
# around intended use-cases:
#
# - "admin": has all permissions on the resource
#
# - "collaborator": has "read", "list_children", and "create_child", plus
# the "admin" role for child resources. The idea is that if you're an
# Organization Collaborator, you have full control over the Projects within
# the Organization, but you cannot modify or delete the Organization itself.
# - "collaborator": has "read", "list_children", and "create_child", plus roles
# or permissions on child resources as explicitly defined below
#
# - "viewer": has "read" and "list_children" on a resource
# - "viewer": has "read" and "list_children" on the resource
#
# Each resource defines its own role hierarchy and the permissions granted by
# each role below. Consequently, similarly named roles do not necessarily have
# identical effects at different scopes.
#
# A role on one resource does not automatically propagate to related resources.
# It grants permissions or roles on those resources only where an explicit
# relation rule says so. In particular, a Fleet role does not by itself grant
# access to the contents of a Silo.
#
# Below the Project level, permissions are granted via roles at the Project
# level. For example, for someone to be able to create, modify, or delete any
# Instances, they must be granted project.collaborator, which means they can
# create, modify, or delete _all_ resources in the Project.
# Instances, they must be granted at least project.limited-collaborator.
#
# The complete set of predefined roles:
#
# - fleet.admin (superuser for the whole system)
# - fleet.collaborator (can manage Silos)
# - fleet.viewer (can read most non-siloed resources in the system)
# - silo.admin (superuser for the silo)
# - silo.collaborator (can create and own Organizations; grants project.admin on all projects)
# - silo.limited-collaborator (grants project.limited-collaborator on all projects)
# - silo.viewer (can read most resources within the Silo; grants project.viewer)
# - organization.admin (complete control over an organization)
# - organization.collaborator (can manage Projects)
# - organization.viewer (can read most resources within the Organization)
# - project.admin (complete control over a Project)
# - project.collaborator (can manage all resources within the Project, including networking)
# - project.limited-collaborator (can manage compute resources, but not networking resources)
# - project.viewer (can read most resources within the Project)
# - fleet.admin
# (full control of the Fleet and explicitly delegated resources)
# - fleet.collaborator
# (can create, modify, and delete Silo objects, but receives no role within
# them)
# - fleet.viewer
# (can read the Fleet and resources that explicitly delegate access from it)
# - silo.admin
# (full control of the Silo and its resources)
# - silo.collaborator
# (can create Projects and grants project.admin on all Projects within a given
# Silo)
# - silo.limited-collaborator
# (grants project.limited-collaborator on all Projects within a given Silo)
# - silo.viewer
# (can read selected Silo resources and grants project.viewer on all Projects
# within a given Silo)
# - project.admin
# (full control of a Project and its resources)
# - project.collaborator
# (can manage all resources within the Project, including networking)
# - project.limited-collaborator
# (can manage compute and related resources, but not networking
# infrastructure)
# - project.viewer
# (can read most resources within the Project)
#
# Outside the Silo/Organization/Project hierarchy, we (currently) treat most
# Outside the Silo/Project hierarchy, we (currently) treat most
# resources as nested under Fleet or else a synthetic resource (see below). We
# do not yet support role assignments on anything other than Fleet, Silo,
# Organization, or Project.
#
# do not yet support role assignments on anything other than Fleet, Silo, or
# Project.

# "Fleet" is a global singleton representing the whole system. The name comes
# from the idea described in RFD 24, but it's not quite right. This probably
Expand Down Expand Up @@ -159,24 +176,17 @@ resource Silo {
has_relation(fleet: Fleet, "parent_fleet", silo: Silo)
if silo.fleet = fleet;

# As a special case, all authenticated users can read their own Silo. That's
# not quite the same as having the "viewer" role. For example, they cannot list
# Organizations in the Silo.
#
# One reason this is necessary is because if an unprivileged user tries to
# create an Organization using "POST /organizations", they should get back a 403
# (which implies they're able to see /organizations, which is essentially seeing
# the Silo itself) rather than a 404. This behavior isn't a hard constraint
# (i.e., you could reasonably get a 404 for an API you're not allowed to call).
# Nor is the implementation (i.e., we could special-case this endpoint somehow).
# But granting this permission is the simplest way to keep this endpoint's
# behavior consistent with the rest of the API.
Comment on lines -166 to -173

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 believe this is still true if you s/organization/project/, FWIW. We may not need the comment any more now that we have the policy test.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ah! In that case, it could still be worth mentioning the why between the two status codes, so I'll add the bulk of the comment back in, just focussing on projects instead of organizations.

# As a special case, every authenticated Silo user can read their own Silo even
# if they have no role on it. This grants only the "read" permission; it does
# not confer the "viewer" role or its "list_children" permission.
#
# This rule is also used to determine if a user can list the identity providers
# in the Silo (which they should be able to), since that's predicated on being
# able to read the Silo.
# Among other things, this ensures that an unauthorized attempt to create a
# Project returns 403 rather than 404: authorization failures are reported as
# not found when the actor cannot read the resource.
#
# It's unclear what else would break if users couldn't see their own Silo.
# This permission also allows users to list the identity providers in their
# Silo, since access to that collection is predicated on being able to read the
# parent Silo.
has_permission(actor: AuthenticatedActor, "read", silo: Silo)
if actor.is_user and silo in actor.silo;

Expand Down
Loading