fleet/server/authz/policy.rego
Juan Fernandez 1bc32467a7
Implement GET /api/v1/fleet/rest_api (#42883)
**Related issue:** Resolves #42883 

Added a new premium GET /api/_version_/fleet/rest_api endpoint that
returns the contents of the embedded `api_endpoints.yml` artifact.
2026-04-10 11:12:38 -04:00

1318 lines
38 KiB
Rego

# See OPA documentation for specification of this policy language:
# https://www.openpolicyagent.org/docs/latest/policy-language/
package authz
import input.action
import input.object
import input.subject
# Constants
# Actions
read := "read"
list := "list"
write := "write"
create := "create" # only for labels right now
write_host_label := "write_host_label"
cancel_host_activity := "cancel_host_activity"
resend := "resend" # only for profiles, and to a single host
read_secrets := "read_secrets"
# User specific actions
write_role := "write_role"
change_password := "change_password"
# Action used on object "targeted_query" used for running live queries.
run := "run"
# Action used on object "query" used for running "new" live queries.
run_new := "run_new"
# Selective prefixes over actions mean that they can be allowed in specific
# cases for roles that usually aren't allowed to perform them.
selective_read := "selective_read"
selective_list := "selective_list"
# Roles
admin := "admin"
maintainer := "maintainer"
observer := "observer"
observer_plus := "observer_plus"
gitops := "gitops"
technician := "technician"
# Default deny
default allow = false
# team_role gets the role that the subject has for the team, returning undefined
# if the user has no explicit role for that team.
team_role(subject, team_id) = role {
subject_team := subject.teams[_]
subject_team.id == team_id
role := subject_team.role
}
##
# Global config
##
# Global admin, gitops, maintainer, technician, observer_plus and observer can read global config.
allow {
object.type == "app_config"
subject.global_role == [admin, gitops, maintainer, technician, observer_plus, observer][_]
action == read
}
# Team admin, maintainer, technician, observer_plus, and observer can read global config.
allow {
object.type == "app_config"
# If role is admin, gitops, maintainer, technician, observer_plus, or observer on any team.
team_role(subject, subject.teams[_].id) == [admin, gitops, maintainer, technician, observer_plus, observer][_]
action == read
}
# Global admins and gitops can write global config.
allow {
object.type == "app_config"
subject.global_role == [admin, gitops][_]
action == write
}
# Global admin, gitops, maintainer, technician, observer_plus and observer can read Okta IdP assets.
allow {
object.type == "conditional_access_idp_assets"
subject.global_role == [admin, gitops, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# Teams
##
# Any logged in user can read teams (service must filter appropriately based on
# access) if the overall object is specified
allow {
object.type == "team"
object.id == 0
not is_null(subject)
action == read
}
# Global admins, maintainers, technicians, observer_plus and observers can read teams.
allow {
object.type == "team"
object.id != 0
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team admins, maintainers, technicians, observer_plus and observers can read their team.
allow {
object.type == "team"
object.id != 0
team_role(subject, object.id) == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Global admins and gitops can write teams.
allow {
object.type == "team"
subject.global_role == [admin, gitops][_]
action == write
}
# Team admins and gitops can write their teams.
allow {
object.type == "team"
team_role(subject, object.id) == [admin, gitops][_]
action == write
}
##
# Users
#
# NOTE: More rules apply to users but they are implemented in Go code.
# Our end goal is to move all the authorization logic here.
##
# Any user can read and write self and change their own password.
allow {
object.type == "user"
object.id == subject.id
object.id != 0
action == [read, write, change_password][_]
}
# Global admins can perform all operations on all users.
allow {
object.type == "user"
subject.global_role == admin
action == [read, write, write_role, change_password][_]
}
# Global observers, observer_plus, technicians, and maintainers can read users.
allow {
object.type == "user"
subject.global_role == [observer, observer_plus, technician, maintainer][_]
action == read
}
# Team admins can perform all operations on the team users (except changing their password).
allow {
object.type == "user"
team_role(subject, object.teams[_].id) == admin
action == [read, write, write_role][_]
}
##
# Invites
##
# Global admins may read/write invites
allow {
object.type == "invite"
subject.global_role == admin
action == [read,write][_]
}
##
# Activities
##
# Global admins, maintainers, technicians, observer_plus and observers can read activities.
allow {
object.type == "activity"
subject.global_role == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# Sessions
##
# Any user can read/write own session
allow {
object.type == "session"
object.user_id == subject.id
action == [read, write][_]
}
# Admins can read/write all user sessions
allow {
object.type == "session"
subject.global_role == admin
action == [read, write][_]
}
##
# Enroll Secrets
##
# Global admins and maintainers can read/write enroll secrets.
allow {
object.type == "enroll_secret"
subject.global_role == [admin, maintainer][_]
action == [read, write][_]
}
# Global gitops can write global enroll secrets.
allow {
object.type == "enroll_secret"
object.is_global_secret
subject.global_role == gitops
action == write
}
# Team admins and maintainers can read/write for appropriate teams.
allow {
object.type == "enroll_secret"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == [read, write][_]
}
# (Technicians, observer_plus, and observers are not granted read for enroll secrets)
##
# Hosts
##
# allowed_read_roles evaluates which roles are allowed for read based on the given action.
allowed_read_roles(action, base_roles, extra_roles) = result {
action == selective_read
result := base_roles | extra_roles
} else = result {
action == read
result := base_roles
} else = result {
result := null
}
# allowed_list_roles evaluates which roles are allowed for list based on the given action.
allowed_list_roles(action, base_roles, extra_roles) = result {
action == "selective_list"
result := base_roles | extra_roles
} else = result {
action == "list"
result := base_roles
} else = result {
result := null
}
# Global admins, maintainers, technicians, observer_plus and observers can list hosts.
allow {
object.type == "host"
base_roles := {admin, maintainer, technician, observer_plus, observer}
extra_roles := {gitops}
allowed_list_roles(action, base_roles, extra_roles)[_] == subject.global_role
}
# Team admins, maintainers, technicians, observer_plus and observers can list and selective_list hosts.
# Gitops can selective_list hosts
allow {
object.type == "host"
# If role is admin, maintainer, technician, observer_plus or observer on any team.
base_roles := {admin, maintainer, technician, observer_plus, observer}
# Or gitops for selective reads
extra_roles := {gitops}
allowed_list_roles(action, base_roles, extra_roles)[_] == team_role(subject, subject.teams[_].id)
}
# Allow read for global admin/maintainer, selective_read for gitops.
allow {
object.type == "host"
base_roles := {admin, maintainer}
extra_roles := {gitops}
allowed_read_roles(action, base_roles, extra_roles)[_] == subject.global_role
}
# Global gitops, admin and maintainers can write hosts.
allow {
object.type == "host"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Global admin, maintainers, technicians, and gitops can write labels to hosts.
allow {
object.type == "host"
subject.global_role == [admin, maintainer, technician, gitops][_]
action == write_host_label
}
# Global admin and maintainers can cancel activities on a host.
allow {
object.type == "host"
subject.global_role == [admin, maintainer][_]
action == cancel_host_activity
}
# Allow read for global technician, observer, and observer_plus, selective_read for gitops.
allow {
object.type == "host"
base_roles := {technician, observer_plus, observer}
extra_roles := {gitops}
allowed_read_roles(action, base_roles, extra_roles)[_] == subject.global_role
}
# Allow read for matching team admin/maintainer/technician/observer/observer_plus, selective read for gitops.
allow {
object.type == "host"
base_roles := {admin, maintainer, technician, observer, observer_plus}
extra_roles := {gitops}
allowed_read_roles(action, base_roles, extra_roles)[_] == team_role(subject, object.team_id)
}
# Team admins and maintainers can write to hosts of their own team
allow {
object.type == "host"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == write
}
# Team admins, maintainers, technicians, and gitops can write labels to hosts of their own team.
allow {
object.type == "host"
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops][_]
action == write_host_label
}
# Team admins and maintainers can cancel activities on a host of their own team.
allow {
object.type == "host"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == cancel_host_activity
}
##
# Host health
##
# Global admins, maintainers, technicians, observer_plus, and observers can read host health.
allow {
object.type == "host_health"
subject.global_role == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
# Team admins, maintainers, technicians, observer_plus, and observers can read host health of their own team.
allow {
object.type == "host_health"
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# Labels
##
# Global admins, maintainers, technicians, observer_plus, observers and gitops can read labels.
allow {
object.type == "label"
subject.global_role == [admin, maintainer, technician, observer_plus, observer, gitops][_]
action == read
}
# Team admins, maintainers, technicians, observer_plus, observers and gitops can read global labels.
allow {
object.type == "label"
any([is_null(object.team_id), object.team_id == 0]) # allow specifying team ID 0 for listing exclusively global labels
# If role is admin, maintainer, technician, observer_plus or observer on any team.
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus, observer, gitops][_]
action == read
}
# Global admins, maintainers, technicians, and gitops can write labels
allow {
object.type == "label"
subject.global_role == [admin, maintainer, technician, gitops][_]
action == write
}
# Global admins, maintainers, technicians, and gitops can create labels
allow {
object.type == "label"
subject.global_role == [admin, maintainer, technician, gitops][_]
action == create
}
# Team admins, maintainers, technicians, and gitops can create global labels
allow {
object.type == "label"
is_null(object.team_id)
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, gitops][_]
action == create
}
# Team admins, maintainers, technicians, and gitops can write global labels they created
allow {
object.type == "label"
is_null(object.team_id)
not is_null(object.author_id)
object.author_id = subject.id
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, gitops][_]
action == write
}
# Team users can read labels on their team
allow {
object.type == "label"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, gitops, technician, observer_plus, observer][_]
action == read
}
# Team admins, maintainers, technicians, and gitops can write labels on their team
allow {
object.type == "label"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops][_]
action == write
}
# Team admins, maintainers, technicians, and gitops can create labels on their team
allow {
object.type == "label"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops][_]
action == create
}
##
# Queries
##
# Global admins, maintainers and gitops can write queries.
allow {
object.type == "query"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Global admins, maintainers, technicians, gitops, observer_plus and observers can read queries.
allow {
object.type == "query"
subject.global_role == [admin, maintainer, technician, gitops, observer_plus, observer][_]
action == read
}
# Team admin, maintainers and gitops can write queries for their teams.
allow {
object.type == "query"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == write
}
# Team admins, maintainers, technicians, gitops, observer_plus and observers can read queries for their teams.
allow {
object.type == "query"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops, observer_plus, observer][_]
action == read
}
# Team admins, maintainers, technicians, observer_plus and observers can read global queries.
allow {
object.type == "query"
is_null(object.team_id)
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
# Global admins, maintainers, technicians, and observer_plus can run any query saved query.
allow {
object.type == "targeted_query"
subject.global_role == [admin, maintainer, technician, observer_plus][_]
action = run
}
# Global admins, maintainers, technician, and observer_plus can run any new query.
allow {
object.type == "query"
subject.global_role == [admin, maintainer, technician, observer_plus][_]
action = run_new
}
# Team admin, maintainer, technician, and observer_plus running a global non-observers_can_run query
# must have the targets filtered to only teams that they maintain.
allow {
object.type == "targeted_query"
object.observer_can_run == false
is_null(subject.global_role)
action == run
is_null(object.team_id)
not is_null(object.host_targets.teams)
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin, maintainer, technician, observer_plus][_] }
count(ok_teams) == count(object.host_targets.teams)
}
# Team admin, maintainer, technician, and observer_plus running a non-observers_can_run query that belongs to their team
# must have the targets filtered to only teams that they maintain.
allow {
object.type == "targeted_query"
object.observer_can_run == false
is_null(subject.global_role)
action == run
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus][_]
not is_null(object.host_targets.teams)
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin, maintainer, technician, observer_plus][_] }
count(ok_teams) == count(object.host_targets.teams)
}
# Team admin, maintainer, technician, and observer_plus running a global non-observers_can_run query when no target teams are specified.
allow {
object.type == "targeted_query"
object.observer_can_run == false
is_null(subject.global_role)
action == run
is_null(object.team_id)
# If role is admin, maintainer, technician, or observer_plus on any team.
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus][_]
# and there are no team targets
is_null(object.host_targets.teams)
}
# Team admin, maintainer, technician, and observer_plus running a non-observers_can_run query that belongs to their team when no target teams are specified.
allow {
object.type == "targeted_query"
object.observer_can_run == false
is_null(subject.global_role)
action == run
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus][_]
# there are no team targets
is_null(object.host_targets.teams)
}
# Team admin, maintainer, technician, and observer_plus can run a new query.
allow {
object.type == "query"
# If role is admin, maintainer, technician, or observer_plus on any team.
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus][_]
action == run_new
}
# Global observers can run observer_can_run global queries (`null` team_id).
allow {
object.type == "targeted_query"
object.observer_can_run == true
subject.global_role == observer
action = run
is_null(object.team_id)
}
# Global observers can run observer_can_run team queries only targeting that team.
allow {
object.type == "targeted_query"
object.observer_can_run == true
subject.global_role == observer
action = run
not is_null(object.team_id)
not is_null(object.host_targets.teams)
ok_teams := { tmid | tmid := object.host_targets.teams[_]; tmid == object.team_id }
count(ok_teams) == count(object.host_targets.teams)
}
# Global observers can run observer_can_run team queries when no target teams are specified.
allow {
object.type == "targeted_query"
object.observer_can_run == true
subject.global_role == observer
action = run
not is_null(object.team_id)
is_null(object.host_targets.teams)
}
# Team admin, maintainer, technician, observer_plus and observer running a global observers_can_run query must have the targets
# filtered to only teams that they observe.
allow {
object.type == "targeted_query"
object.observer_can_run == true
is_null(subject.global_role)
action == run
is_null(object.team_id)
not is_null(object.host_targets.teams)
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin, maintainer, technician, observer_plus, observer][_] }
count(ok_teams) == count(object.host_targets.teams)
}
# Team admin, maintainer, technician, observer_plus, and observer running an observers_can_run query that belongs to their team must have the targets
# filtered to only teams that they observe. Observers may only target the query's own team; admin/maintainer/etc. may target any team they have such a role on.
allow {
object.type == "targeted_query"
object.observer_can_run == true
is_null(subject.global_role)
action == run
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus, observer][_]
not is_null(object.host_targets.teams)
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin, maintainer, technician, observer_plus][_] } | { tmid | tmid := object.host_targets.teams[_]; tmid == object.team_id; team_role(subject, tmid) == observer }
count(ok_teams) == count(object.host_targets.teams)
}
# Team admin, maintainer, technician, observer_plus, and observer running a global observers_can_run query and there are no target teams.
allow {
object.type == "targeted_query"
object.observer_can_run == true
is_null(subject.global_role)
action == run
is_null(object.team_id)
# If role is admin, maintainer, technician, observer_plus, or observer on any team.
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus, observer][_]
# and there are no team targets
is_null(object.host_targets.teams)
}
# Team admin, maintainer, technician, observer_plus and observer running an observers_can_run query that belongs to their team and there are no target teams.
allow {
object.type == "targeted_query"
object.observer_can_run == true
is_null(subject.global_role)
action == run
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus, observer][_]
# there are no team targets
is_null(object.host_targets.teams)
}
##
# Targets
##
# Global admin, maintainer, technician, observer_plus, and observer can read targets.
allow {
object.type == "target"
subject.global_role == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
# Team admin, maintainer, technician, observer_plus and observer can read global config.
allow {
object.type == "target"
# If role is admin, maintainer, technician, observer_plus or observer on any team.
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# 2017 Packs (deprecated)
##
# Global admins, maintainers and gitops can read/write 2017 packs.
allow {
object.type == "pack"
subject.global_role == [admin, maintainer, gitops][_]
action == [read, write][_]
}
##
# File Carves
##
# Only global admins can read/write carves
allow {
object.type == "carve"
subject.global_role == admin
action == [read, write][_]
}
##
# Policies
##
# Global admins, maintainers, and gitops can read and write policies.
allow {
object.type == "policy"
subject.global_role == [admin, maintainer, gitops][_]
action == [read, write][_]
}
# Global technician, observer, and observer_plus can read any policies.
allow {
object.type == "policy"
subject.global_role == [technician, observer, observer_plus][_]
action == read
}
# Team admin, maintainers, and gitops can read and write policies for their teams.
allow {
not is_null(object.team_id)
object.type == "policy"
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == [read, write][_]
}
# Team admin, maintainers, technician, observers, and observers_plus can read global policies
allow {
is_null(object.team_id)
object.type == "policy"
team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team technician, observer, and observer_plus can read policies for their teams.
allow {
not is_null(object.team_id)
object.type == "policy"
team_role(subject, object.team_id) == [technician, observer, observer_plus][_]
action == read
}
##
# Software
##
# Global admins, maintainers, technician, observers, and observer_plus can read all software.
allow {
object.type == "software_inventory"
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Only global admins can modify software inventory (specifically software title names)
allow {
object.type == "software_inventory"
subject.global_role == admin
action == write
}
# Team admins, maintainers, technician, observers and observer_plus can read all software in their teams.
allow {
not is_null(object.team_id)
object.type == "software_inventory"
team_role(subject, object.team_id) == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Global admins and maintainers can read all maintained apps.
allow {
object.type == "maintained_app"
subject.global_role == [admin, maintainer][_]
action == read
}
# Team admins and maintainers can read all maintained apps (no team constraint, unlike installers)
allow {
object.type == "maintained_app"
team_role(subject, subject.teams[_].id) == [admin, maintainer][_]
action == read
}
# Global admins, maintainers, and technicians can read any installable entity (software installer or VPP app)
allow {
object.type == "installable_entity"
subject.global_role == [admin, maintainer, technician][_]
action == read
}
# Global admins, maintainers, and gitops can write any installable entity (software installer or VPP app)
allow {
object.type == "installable_entity"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Team admins, maintainers, and technicians can read any installable entity (software installer or VPP app) in their teams.
allow {
not is_null(object.team_id)
object.type == "installable_entity"
team_role(subject, object.team_id) == [admin, maintainer, technician][_]
action == read
}
# Team admins, maintainers, and gitops can write any installable entity (software installer or VPP app) in their teams.
allow {
not is_null(object.team_id)
object.type == "installable_entity"
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == write
}
##
# Host software installs
##
# Global admins, maintainers, and technicians can write (install/uninstall) software on hosts (not
# gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_software_installer_result"
subject.global_role == [admin, maintainer, technician][_]
action == write
}
# Team admin, maintainers, and technicians can write (install/uninstall) software on hosts for their
# teams (not gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_software_installer_result"
not is_null(object.host_team_id)
team_role(subject, object.host_team_id) == [admin, maintainer, technician][_]
action == write
}
# Global admins, maintainers, technicians, observers and observer_plus can read software install results on hosts
# (not gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_software_installer_result"
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team admin, maintainer, technician, observer and observer_plus can read software install results on hosts for their teams
# (not gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_software_installer_result"
not is_null(object.host_team_id)
team_role(subject, object.host_team_id) == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
##
# Apple, Windows, and Android configuration profiles.
# (Linux uses synthetic profiles to display disk encryption.)
##
# Global admins, maintainers, and gitops can write MDM config profiles.
allow {
object.type == "mdm_config_profile"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Global admins, maintainers, technicians, and gitops can read MDM config profiles.
allow {
object.type == "mdm_config_profile"
subject.global_role == [admin, maintainer, technician, gitops][_]
action == read
}
# Global admins, maintainers, technicians, and gitops can resend MDM config profiles.
#
# GitOps doesn't really need permissions to resend to specific hosts,
# but we will keep this as-is to not break any workflows that might be using a
# GitOps token to do a resend.
allow {
object.type == "mdm_config_profile"
subject.global_role == [admin, maintainer, technician, gitops][_]
action == resend
}
# Team admins, maintainers and gitops can write MDM config profiles on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_config_profile"
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == write
}
# Team admins, maintainers, technicians and gitops can read MDM config profiles on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_config_profile"
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops][_]
action == read
}
# Team admins, maintainers, technicians, and gitops can resend MDM config profiles on their teams.
#
# GitOps doesn't really need permissions to resend to specific hosts,
# but we will keep this as-is to not break any workflows that might be using a
# GitOps token to do a resend.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_config_profile"
team_role(subject, object.team_id) == [admin, maintainer, technician, gitops][_]
action == resend
}
##
# Apple MDM
##
# Global admins can read, write, and list MDM apple information.
allow {
object.type == "mdm_apple"
subject.global_role == admin
action == [read, write, list][_]
}
# Global admins can read and write Apple MDM enrollments.
allow {
object.type == "mdm_apple_enrollment_profile"
subject.global_role == admin
action == [read, write][_]
}
# Global admins and maintainers can write (execute) MDM commands.
allow {
object.type == "mdm_command"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Team admins and maintainers can write (execute) MDM commands on hosts of their teams.
allow {
not is_null(object.team_id)
object.type == "mdm_command"
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == write
}
# Global admins, maintainers, technicians, observers and observer_plus can read MDM commands.
allow {
object.type == "mdm_command"
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team admins, maintainers, technicians, observers and observer_plus can read MDM commands on hosts of their teams.
allow {
not is_null(object.team_id)
object.type == "mdm_command"
team_role(subject, object.team_id) == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Global admins can read and write Apple MDM installers.
allow {
object.type == "mdm_apple_installer"
subject.global_role == admin
action == [read, write][_]
}
# Global admins can read and write Apple devices.
allow {
object.type == "mdm_apple_device"
subject.global_role == admin
action == [read, write][_]
}
# Global admins can read and write Apple DEP devices.
allow {
object.type == "mdm_apple_dep_device"
subject.global_role == admin
action == [read, write][_]
}
# Global admins and maintainers can read and write MDM Apple settings.
allow {
object.type == "mdm_apple_settings"
subject.global_role == [admin, maintainer][_]
action == [read, write][_]
}
# Global gitops can write MDM Apple settings.
allow {
object.type == "mdm_apple_settings"
subject.global_role == gitops
action == write
}
# Team admins and maintainers can read and write MDM Apple Settings of their teams.
allow {
not is_null(object.team_id)
object.type == "mdm_apple_settings"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == [read, write][_]
}
# Team gitops can write MDM Apple Settings of their teams.
allow {
not is_null(object.team_id)
object.type == "mdm_apple_settings"
team_role(subject, object.team_id) == gitops
action == write
}
# Global admins and maintainers can read and write bootstrap packages.
allow {
object.type == "mdm_apple_bootstrap_package"
subject.global_role == [admin, maintainer][_]
action == [read, write][_]
}
# Global gitops can write bootstrap packages.
allow {
object.type == "mdm_apple_bootstrap_package"
subject.global_role == gitops
action == write
}
# Team admins and maintainers can read and write bootstrap packages on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_apple_bootstrap_package"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == [read, write][_]
}
# Team gitops can write bootstrap packages on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_apple_bootstrap_package"
team_role(subject, object.team_id) == gitops
action == write
}
# Global admins can read, write, and list MDM apple eula information.
allow {
object.type == "mdm_apple_eula"
subject.global_role == admin
action == [read, write, list][_]
}
# Global gitops can read and write the EULA.
allow {
object.type == "mdm_apple_eula"
subject.global_role == gitops
action == [read, write][_]
}
##
# MDM Apple Setup Assistant
##
# Global admins and maintainers can read and write macos setup assistants.
allow {
object.type == "mdm_apple_setup_assistant"
subject.global_role == [admin, maintainer][_]
action == [read, write][_]
}
# Global gitops can write macos setup assistants.
allow {
object.type == "mdm_apple_setup_assistant"
subject.global_role == gitops
action == write
}
# Team admins and maintainers can read and write macos setup assistants on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_apple_setup_assistant"
team_role(subject, object.team_id) == [admin, maintainer][_]
action == [read, write][_]
}
# Team gitops can write macos setup assistants on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "mdm_apple_setup_assistant"
team_role(subject, object.team_id) == gitops
action == write
}
# Any logged in user can read the manual enrollment profile data.
allow {
object.type == "mdm_apple_manual_enrollment_profile"
not is_null(subject)
action == read
}
##
# Cron schedules
##
# Global admins can read and write (i.e. trigger) cron schedules.
allow {
object.type == "cron_schedules"
subject.global_role == admin
action == [read, write][_]
}
##
# Version
##
# Any logged in user can read Fleet's version
allow {
object.type == "version"
not is_null(subject)
action == read
}
##
# Single host script result (script execution and output)
##
# Global admins, maintainers, and technicians can write (execute) scripts (not
# gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_script_result"
subject.global_role == [admin, maintainer, technician][_]
action == write
}
# Global admins, maintainers, technicians, observer_plus and observers can read script results,
# including software uninstall results.
allow {
object.type == "host_script_result"
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team admin, maintainers, and technicians can write (execute) scripts for their
# teams (not gitops as this is not something that relates to fleetctl gitops).
allow {
object.type == "host_script_result"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician][_]
action == write
}
# Team admins, maintainers, technicians, observer_plus and observers can read script results for their teams, including software uninstall results.
allow {
object.type == "host_script_result"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# Scripts (saved script)
##
# Global admins, maintainers, and gitops can write (upload) saved scripts.
allow {
object.type == "script"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Global admins, maintainers, technicians, observer_plus and observers can read scripts.
allow {
object.type == "script"
subject.global_role == [admin, maintainer, technician, observer, observer_plus][_]
action == read
}
# Team admin, maintainers, and gitops can write (upload) saved scripts for their teams.
allow {
object.type == "script"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == write
}
# Team admins, maintainers, technicians, observer_plus and observers can read scripts for their teams.
allow {
object.type == "script"
not is_null(object.team_id)
team_role(subject, object.team_id) == [admin, maintainer, technician, observer_plus, observer][_]
action == read
}
##
# Secret variables
##
# Global admins, maintainers, and gitops can write secret variables.
allow {
object.type == "secret_variable"
subject.global_role == [admin, maintainer, gitops][_]
action == write
}
# Any global user can read secret variables.
#
# Read permission here is just about being able to read the names and ids, not the content (value).
allow {
object.type == "secret_variable"
# We specify all current roles to be secure in case new future role with less permissions is added to the application
subject.global_role == [admin, maintainer, gitops, technician, observer_plus, observer][_]
action == read
}
# Any team user can read secret variables.
#
# Read permission here is just about being able to read the names and ids, not the content (value).
allow {
object.type == "secret_variable"
# We specify all current team roles to be secure in case new future role with less permissions is added to the application
team_role(subject, subject.teams[_].id) == [admin, maintainer, gitops, technician, observer_plus, observer][_]
action == read
}
##
# Android
##
# Global admins can connect enterprise.
allow {
object.type == "android_enterprise"
subject.global_role == admin
action == [read, write][_]
}
##
# SCIM (System for Cross-domain Identity Management)
##
# Global admins and maintainers can access SCIM.
allow {
object.type == "scim_user"
subject.global_role == [admin, maintainer][_]
action == [read, write][_]
}
##
# Microsoft Compliance Partner
##
# Global admins can configure Microsoft conditional access.
allow {
object.type == "conditional_access_microsoft"
subject.global_role == admin
action == write
}
##
# Certificate Authorities
##
# Global admins and GitOps can configure, read, list, and read secrets of certificate authorities.
allow {
object.type == "certificate_authority"
subject.global_role == [admin, gitops][_]
action == [read, write, list, read_secrets][_]
}
# Global maintainers can read and list certificate authorities
# so they can create certificate templates.
allow {
object.type == "certificate_authority"
subject.global_role == maintainer
action == [read, list][_]
}
# Team admins, maintainers and gitops can read and list certificate authorities
# so they can add certificate templates to their teams.
allow {
object.type == "certificate_authority"
team_role(subject, subject.teams[_].id) == [admin, maintainer, gitops][_]
action == [read, list][_]
}
# Global admins and maintainers can write a certificate request
allow {
object.type == "certificate_request"
subject.global_role == [admin, maintainer][_]
action == write
}
##
# Certificate Templates
##
# Global admins, maintainers and gitops can read and write certificate templates.
allow {
object.type == "certificate_template"
subject.global_role == [admin, maintainer, gitops][_]
action == [read, write][_]
}
# Team admins, maintainers and gitops can read and write certificate templates on their teams.
allow {
not is_null(object.team_id)
object.team_id != 0
object.type == "certificate_template"
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
action == [read, write][_]
}
##
# API Endpoints
##
# Global admins can read API endpoints.
allow {
object.type == "api_endpoint"
subject.global_role == admin
action == read
}
# Any team admin can read API endpoints.
allow {
object.type == "api_endpoint"
team_role(subject, subject.teams[_].id) == admin
action == read
}