mirror of
https://github.com/empayre/fleet.git
synced 2024-11-07 01:15:22 +00:00
9191f4ce66
* WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
559 lines
12 KiB
Rego
559 lines
12 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"
|
|
|
|
# User specific actions
|
|
write_role := "write_role"
|
|
change_password := "change_password"
|
|
|
|
# Query specific actions
|
|
run := "run"
|
|
run_new := "run_new"
|
|
|
|
# Roles
|
|
admin := "admin"
|
|
maintainer := "maintainer"
|
|
observer := "observer"
|
|
|
|
# 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
|
|
##
|
|
|
|
# Any logged in user can read global config
|
|
allow {
|
|
object.type == "app_config"
|
|
not is_null(subject)
|
|
action == read
|
|
}
|
|
|
|
# Admin can write global config
|
|
allow {
|
|
object.type == "app_config"
|
|
subject.global_role == admin
|
|
action == write
|
|
}
|
|
|
|
##
|
|
# 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
|
|
}
|
|
# For specific teams, only members can read
|
|
allow {
|
|
object.type == "team"
|
|
object.id != 0
|
|
team_role(subject, object.id) == [admin,maintainer][_]
|
|
action == read
|
|
}
|
|
# or global admins or global maintainers
|
|
allow {
|
|
object.type == "team"
|
|
object.id != 0
|
|
subject.global_role == [admin, maintainer][_]
|
|
action == read
|
|
}
|
|
|
|
# Admin can write teams
|
|
allow {
|
|
object.type == "team"
|
|
subject.global_role == admin
|
|
action == write
|
|
}
|
|
|
|
# Team admin can write teams
|
|
allow {
|
|
object.type == "team"
|
|
team_role(subject, object.id) == admin
|
|
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][_]
|
|
}
|
|
|
|
# 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
|
|
##
|
|
|
|
# Only global users can read activities
|
|
allow {
|
|
not is_null(subject.global_role)
|
|
object.type == "activity"
|
|
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 all
|
|
allow {
|
|
object.type == "enroll_secret"
|
|
subject.global_role == [admin, maintainer][_]
|
|
action == [read, 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][_]
|
|
}
|
|
|
|
# (Observers are not granted read for enroll secrets)
|
|
|
|
##
|
|
# Hosts
|
|
##
|
|
|
|
# Allow anyone to list (must be filtered appropriately by the service).
|
|
allow {
|
|
object.type == "host"
|
|
not is_null(subject)
|
|
action == list
|
|
}
|
|
|
|
# Allow read/write for global admin/maintainer
|
|
allow {
|
|
object.type == "host"
|
|
subject.global_role = admin
|
|
action == [read, write][_]
|
|
}
|
|
allow {
|
|
object.type == "host"
|
|
subject.global_role = maintainer
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# Allow read for global observer
|
|
allow {
|
|
object.type == "host"
|
|
subject.global_role = observer
|
|
action == read
|
|
}
|
|
|
|
# Allow read for matching team admin/maintainer/observer
|
|
allow {
|
|
object.type == "host"
|
|
team_role(subject, object.team_id) == [admin, maintainer, observer][_]
|
|
action == read
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
##
|
|
# Labels
|
|
##
|
|
|
|
# All users can read labels
|
|
allow {
|
|
object.type == "label"
|
|
not is_null(subject)
|
|
action == read
|
|
}
|
|
|
|
# Only global admins and maintainers can write labels
|
|
allow {
|
|
object.type == "label"
|
|
subject.global_role == admin
|
|
action == write
|
|
}
|
|
allow {
|
|
object.type == "label"
|
|
subject.global_role == maintainer
|
|
action == write
|
|
}
|
|
|
|
##
|
|
# Queries
|
|
##
|
|
|
|
# All users can read queries
|
|
allow {
|
|
not is_null(subject)
|
|
object.type == "query"
|
|
action == read
|
|
}
|
|
|
|
# Global admins and maintainers can write queries
|
|
allow {
|
|
object.type == "query"
|
|
subject.global_role == admin
|
|
action == write
|
|
}
|
|
allow {
|
|
object.type == "query"
|
|
subject.global_role == maintainer
|
|
action == write
|
|
}
|
|
|
|
# Team admins and maintainers can create new queries
|
|
allow {
|
|
object.id == 0 # new queries have ID zero
|
|
object.type == "query"
|
|
team_role(subject, subject.teams[_].id) == [admin, maintainer][_]
|
|
action == write
|
|
}
|
|
|
|
# Team admins and maintainers can edit and delete only their own queries
|
|
allow {
|
|
object.author_id == subject.id
|
|
object.type == "query"
|
|
team_role(subject, subject.teams[_].id) == [admin,maintainer][_]
|
|
action == write
|
|
}
|
|
|
|
# Global admins and maintainers can run any
|
|
allow {
|
|
object.type == "targeted_query"
|
|
subject.global_role == admin
|
|
action = run
|
|
}
|
|
allow {
|
|
object.type == "targeted_query"
|
|
subject.global_role == maintainer
|
|
action = run
|
|
}
|
|
allow {
|
|
object.type == "query"
|
|
subject.global_role == admin
|
|
action = run_new
|
|
}
|
|
allow {
|
|
object.type == "query"
|
|
subject.global_role == maintainer
|
|
action = run_new
|
|
}
|
|
|
|
# Team admin and maintainer running a 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
|
|
|
|
not is_null(object.host_targets.teams)
|
|
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin,maintainer][_] }
|
|
count(ok_teams) == count(object.host_targets.teams)
|
|
}
|
|
|
|
# Team admin and maintainer running a 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
|
|
|
|
# If role is admin or maintainer on any team
|
|
team_role(subject, subject.teams[_].id) == [admin,maintainer][_]
|
|
|
|
# and there are no team targets
|
|
is_null(object.host_targets.teams)
|
|
}
|
|
|
|
# Team admin and maintainer can run a new query
|
|
allow {
|
|
object.type == "query"
|
|
# If role is admin or maintainer on any team
|
|
team_role(subject, subject.teams[_].id) == [admin,maintainer][_]
|
|
action == run_new
|
|
}
|
|
|
|
# Observers can run only if observers_can_run
|
|
allow {
|
|
object.type == "targeted_query"
|
|
object.observer_can_run == true
|
|
subject.global_role == observer
|
|
action = run
|
|
}
|
|
|
|
# Team observer running a 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
|
|
|
|
not is_null(object.host_targets.teams)
|
|
ok_teams := { tmid | tmid := object.host_targets.teams[_]; team_role(subject, tmid) == [admin,maintainer,observer][_] }
|
|
count(ok_teams) == count(object.host_targets.teams)
|
|
}
|
|
|
|
# Team observer running a 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
|
|
|
|
# If role is admin, maintainer or observer on any team
|
|
team_role(subject, subject.teams[_].id) == [admin,maintainer,observer][_]
|
|
|
|
# and there are no team targets
|
|
is_null(object.host_targets.teams)
|
|
}
|
|
|
|
##
|
|
# Targets
|
|
##
|
|
|
|
# All users can read targets (filtered appropriately based on their
|
|
# teams/roles).
|
|
allow {
|
|
not is_null(subject)
|
|
object.type == "target"
|
|
action == read
|
|
}
|
|
|
|
##
|
|
# Packs
|
|
##
|
|
|
|
# Global admins and maintainers can read/write all packs.
|
|
allow {
|
|
object.type == "pack"
|
|
subject.global_role == [admin, maintainer][_]
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# All users can read the global pack.
|
|
allow {
|
|
object.type == "pack"
|
|
not is_null(subject)
|
|
object.is_global_pack == true
|
|
action == read
|
|
}
|
|
|
|
# Team admins, maintainers and observers can read their team's pack.
|
|
#
|
|
# NOTE: Action "read" on a team's pack includes listing its scheduled queries.
|
|
allow {
|
|
object.type == "pack"
|
|
not is_null(object.pack_team_id)
|
|
team_role(subject, object.pack_team_id) == [admin, maintainer, observer][_]
|
|
action == read
|
|
}
|
|
|
|
# Team admins and maintainers can add/remove scheduled queries from/to their team's pack.
|
|
#
|
|
# NOTE: The team's pack is not editable per-se, it's a special pack to group
|
|
# all the team's scheduled queries. So the "write" operation only covers
|
|
# adding/removing scheduled queries from the pack.
|
|
allow {
|
|
object.type == "pack"
|
|
not is_null(object.pack_team_id)
|
|
team_role(subject, object.pack_team_id) == [admin, maintainer][_]
|
|
action == write
|
|
}
|
|
|
|
##
|
|
# File Carves
|
|
##
|
|
|
|
# Only global admins can read/write carves
|
|
allow {
|
|
object.type == "carve"
|
|
subject.global_role == admin
|
|
action == [read, write][_]
|
|
}
|
|
|
|
##
|
|
# Policies
|
|
##
|
|
|
|
# Global Admin and Maintainer can read and write policies
|
|
allow {
|
|
object.type == "policy"
|
|
subject.global_role == [admin,maintainer][_]
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# Global Observer can read any policies
|
|
allow {
|
|
object.type == "policy"
|
|
subject.global_role == observer
|
|
action == read
|
|
}
|
|
|
|
# Team admin and maintainers 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][_]
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# Team admin, maintainers and observers can read global policies
|
|
allow {
|
|
is_null(object.team_id)
|
|
object.type == "policy"
|
|
team_role(subject, subject.teams[_].id) == [admin,maintainer,observer][_]
|
|
action == read
|
|
}
|
|
|
|
# Team Observer can read policies for their teams
|
|
allow {
|
|
not is_null(object.team_id)
|
|
object.type == "policy"
|
|
team_role(subject, object.team_id) == observer
|
|
action == read
|
|
}
|
|
|
|
##
|
|
# Software
|
|
##
|
|
|
|
# Global users can read all software.
|
|
allow {
|
|
object.type == "software_inventory"
|
|
subject.global_role == [admin, maintainer, observer][_]
|
|
action == read
|
|
}
|
|
|
|
# Team users 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, observer][_]
|
|
action == read
|
|
}
|
|
|
|
##
|
|
# Apple MDM
|
|
##
|
|
|
|
# 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 can read and write Apple commands.
|
|
allow {
|
|
object.type == "mdm_apple_command"
|
|
subject.global_role == admin
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# Global admins can read and write Apple MDM command results.
|
|
allow {
|
|
object.type == "mdm_apple_command_result"
|
|
subject.global_role == admin
|
|
action == [read, write][_]
|
|
}
|
|
|
|
# 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][_]
|
|
}
|