diff --git a/docs/api.md b/docs/api.md index 84b24ce..25c62d3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -50,16 +50,18 @@ schemas. ## Authentication If UI/API authentication is enabled (see -[User Authn/Authz](user-administration.md)), API requests must include an -auth token generated from the `Users` tab in the web UI, passed as the -`X-phenix-auth-token` header: +[Users and Authentication](user-administration.md)), API requests must include +a token in the `X-Phenix-Auth-Token` header, prefixed with `Bearer`: ```http -X-phenix-auth-token: ****** +X-Phenix-Auth-Token: Bearer ``` -See [Generating User Authentication Tokens](user-administration.md#generating-user-authentication-tokens) -for details. +Get a token by signing in with `POST /api/v1/login`, or create a longer-lived +one from the `Users` tab. See [Signing In](user-administration.md#signing-in) +and [API Tokens](user-administration.md#api-tokens) for details. What a token +can do depends on the user's role; see +[Roles and Permissions](roles-and-permissions.md). ## Integrations diff --git a/docs/configuration.md b/docs/configuration.md index 2faa9e5..f3c26a1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -637,8 +637,8 @@ that user should have is specified, and using that role name the appropriate RBAC permissions are copied from the role configuration into the user configuration. -There are six (6) default role configurations that get created automatically, -and are described [here](user-administration.md#roles). An example role +phēnix creates a set of default role configurations automatically, described +[here](roles-and-permissions.md#built-in-roles). An example role configuration is shown below for completeness. ```yaml @@ -764,6 +764,14 @@ or experiment configuration using a graphical interface. It is based on the `minibuilder` app in `minimega`. Users can access the Builder app via the `Builder` tab in the phēnix UI. +Opening the Builder and saving topology files locally needs the +[`builder`](roles-and-permissions.md#resource-builder) `get` permission, which +every built-in viewer role has. Creating or updating experiments from the +Builder, and importing topologies from phēnix, also need `experiments` and +`configs` permissions; the built-in +[Builder role](roles-and-permissions.md#builder-builder) has everything the +Builder uses. + ### Creating or Editing a Topology When Builder opens, it does so in a new configuration. If a user wanted to open diff --git a/docs/roles-and-permissions.md b/docs/roles-and-permissions.md new file mode 100644 index 0000000..758d5b1 --- /dev/null +++ b/docs/roles-and-permissions.md @@ -0,0 +1,1088 @@ +# Roles and Permissions + +When [authentication](user-administration.md#authentication-modes) is +enabled, phēnix uses role-based access control (RBAC) to decide what each +user can do. Every user has exactly one role, and a role is a list of +policies that grant permissions on resources. This page explains how +permissions are checked, describes the built-in roles, and lists every +resource and verb phēnix checks. + +## How Permissions Are Checked + +A role is a list of policies. Each policy has: + +* `resources`: the resources it applies to, such as `experiments` or + `vms/snapshots`. +* `verbs`: the actions it allows, such as `list`, `get`, or `update`, or `*` + for all verbs. +* `resourceNames` (optional): the objects it applies to, such as experiment + names. + +```yaml +policies: +- resources: + - experiments + - "experiments/*" + resourceNames: + - exp-a + verbs: + - list + - get +``` + +phēnix applies these rules: + +* **Wildcards.** Resources and resource names use shell-style patterns (`*`, + `?`, `[...]`), where `*` never matches `/`. So `experiments/*` matches + `experiments/start` but not `experiments`, and `*` matches `experiments` but + not `experiments/start`. Global Admin uses both `*` and `*/*` to match + everything. Likewise, `scorch` does not match `scorch/terminals`. +* **Named and unnamed checks.** Many checks name the object being accessed, + such as the experiment, the VM as `/`, or a config as + `/`. A named check passes only if a matching policy lists a + matching resource name; a policy without `resourceNames` never passes a + named check. A name prefixed with `!` excludes matching objects. Checks that + don't name an object, such as creating an experiment or opening the Builder, + ignore `resourceNames`. The [Resources](#resources) tables show what each + check is named with. +* **Lists.** Listing needs the permission without a name, and then filters + the list by name, as described for each resource below. +* **Live updates.** The web UI receives live updates, such as VM state + changes, over a websocket, filtered by the permissions described below. +* **Users hold a copy of their role.** Assigning a role copies its policies + into the user, scoped to the user's resource names. Editing a role config + afterward does not change users who already have the role; reassign the + role on the `Users` tab to apply the changes. Self sign-up users are the + exception: until an administrator assigns them a role, they use the + `disabled` role config directly. +* **Role changes and the UI.** The web UI keeps the role it received at sign + in, so after a user's role changes, the user should sign out and back in. +* **The UI only hides controls.** The web UI hides controls a user's role + doesn't allow, but what a user can do is decided by the server's permission + checks, not by what the UI shows. + +## Scoping a Role to Experiments + +When a role is assigned to a user, the space-separated `Resource Name(s)` from +the `Users` tab (or the extra fields of a [`ui.users`](user-administration.md#from-configuration-uiusers) +entry) are copied into the role's policies that don't already name their +resources, in order, stopping at the first policy that does. This is how roles +such as Experiment User and Scorch Viewer are limited to the user's +experiments. + +* Experiment checks use the experiment name, such as `exp-a`. +* VM checks, including port forwards, use `/`, so enter both + the experiment and a VM pattern, for example `exp-a exp-a/*`. +* Names are patterns, so `exp-*` matches every experiment whose name starts + with `exp-`. A name prefixed with `!` excludes matches, so + `exp-* exp-*/* !exp-secret !exp-secret/*` covers every `exp-` experiment and + its VMs except `exp-secret`. +* Leaving `Resource Name(s)` empty is the same as `*`, which matches every + experiment but no VM, because `*` doesn't match `/`. For access to every + experiment and VM, enter `* */*`. The same applies to + [`ui.users`](user-administration.md#from-configuration-uiusers) entries + without resource names. +* Roles whose policies all name their resources, such as Global Admin, Global + Viewer, and Builder, ignore these names and are not scoped to experiments. +* Builder, Scorch, and Tunneler access (`builder`, `scorch`, + `scorch/terminals`, and `tunneler`) is checked without a name, so scoping + does not limit it. Scorch data is still limited to experiments the user can + read. + +## Built-In Roles + +`Global Admin` is the administrator role and has access to everything, +including user management. The following table gives a high-level overview of +the built-in roles. + +| Role | Limits | List | Get | Create | Update | Patch | Delete | +|-------------------|:-------------------------------------------------------------------------------------------------------------------------|:-----:|:-----:|:------:|:------:|:-----:|:------:| +| Global Admin | Can see and control absolutely anything/everything. | E V U | E V U | E V U | E V U | E V U | E V U | +| Global Viewer | Can see everything, use VM consoles and port forwards, and mount VM disks, but can't change experiments or users. | E V U | E V U | | | | V | +| Experiment Admin | Can see, start, and stop assigned experiments and fully control their VMs, but can't create or delete experiments. | E V | E V | V | E V | V | V | +| Experiment User | Can see assigned experiments and change, redeploy, snapshot, capture, and port-forward their VMs, but can't start, stop, or kill VMs. | E V | E V | V | V | V | V | +| Experiment Viewer | Can see assigned experiments and their VMs, use VM consoles and port forwards, and mount VM disks, but can't change experiments or VMs. | E V | E V | | | | V | +| VM Admin | Can see assigned experiments, and has full administrative control over VMs in assigned experiments. | E V | E V | V | V | V | V | +| VM Viewer | Can see VM screenshots, use VM consoles, and mount VM disks. | V | V | | | | V | +| Scorch Viewer | Can see assigned experiments, their Scorch pipelines, component output, read-only Scorch terminals, and run files. | E | E | | | | | +| Scorch Admin | Everything Scorch Viewer can do, plus start and cancel Scorch runs, type into Scorch terminals, and see VMs. | E V | E V | | | | | +| Builder | Can design topologies and scenarios, and create and update experiments from them. Not scoped to experiments. | E C | E C | E C | E C | | | +| Disabled | Has no permissions. New self sign-up users get this role until an administrator assigns another. | | | | | | | + +Key: E - experiment resource, V - VM resource, U - user resource, C - Topology, Scenario, and Experiment configs + +### Builder, Scorch, and Tunneler Access + +The Builder, Scorch, and Tunneler have their own permissions, described in +[Resources](#builder-scorch-and-tunneler). The built-in roles grant the +following. + +| Role | Builder | Scorch runs | Scorch terminals | Tunneler download | Port forwards | +|-------------------|:--------------------------------|:--------------------|:----------------:|:-----------------:|:-------------:| +| Global Admin | open, save, create, update | view, start, cancel | type, exit | yes | yes | +| Global Viewer | open, save | view | | yes | list, connect | +| Experiment Admin | open, save, create, update [^1] | view, start, cancel | | yes | yes | +| Experiment User | open, save, create [^1] | view, start, cancel | | yes | yes | +| Experiment Viewer | open, save | view | | yes | list, connect | +| VM Admin | | view, start, cancel | | yes | yes | +| VM Viewer | open, save | | | | | +| Scorch Viewer | open, save | view | | | | +| Scorch Admin | | view, start, cancel | type, exit | | | +| Builder | open, save, create, update | | | | | + +[^1]: Creating experiments from the Builder also needs `experiments` + `create`, and importing topologies from phēnix needs `configs` access. + These roles don't have either by default, so in practice they can open + the Builder and save files locally. + +!!! warning "Scorch terminals are shells on the phēnix server" + A Scorch terminal, such as the one a [`break`](scorch.md#break-component) + component opens, is a shell running as the phēnix server process. In a + typical Docker deployment, that is root in a privileged container that + shares the host's process namespace. Anyone who can type into a Scorch + terminal can control the phēnix server, and so can bypass all of phēnix's + access control. For this reason, typing into and exiting Scorch terminals + is a separate permission, [`scorch/terminals`](#resource-scorchterminals) + `write`, from starting and canceling Scorch runs. By default, only Global + Admin and Scorch Admin have it. Only assign it to users trusted with that + access. + +### Upgrading Existing Installs + +The first time `phenix ui` starts after upgrading to a release with Builder, +Scorch, and Tunneler permissions, it keeps existing users working: + +* Built-in roles, and the users assigned to them, get the access in the table + above. Each role is updated once and then annotated with + `phenix.rbac/service-permissions`, so an administrator can remove this + access later without a restart adding it back. +* The Builder, Scorch Viewer, and Scorch Admin roles are created once. If an + administrator deletes one, it is not created again. +* Custom roles are not changed. + +### Built-In Role Definitions + +phēnix creates these role configs when it first starts. They can be viewed +and edited like any other config, for example with +`phenix config get role/experiment-user`. + +#### Global Admin (`global-admin`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: global-admin +spec: + roleName: Global Admin + policies: + - resources: + - "*" + - "*/*" + resourceNames: + - "*" + - "*/*" + verbs: + - "*" +``` + +#### Global Viewer (`global-viewer`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: global-viewer +spec: + roleName: Global Viewer + policies: + - resources: + - "*" + - "*/*" + resourceNames: + - "*" + - "*/*" + verbs: + - list + - get + - resources: + - "vms/mount" + resourceNames: + - "*" + - "*/*" + verbs: + - post + - delete +``` + +#### Experiment Admin (`experiment-admin`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: experiment-admin +spec: + roleName: Experiment Admin + policies: + - resources: + - experiments + - "experiments/*" + verbs: + - list + - get + - update + - resources: + - vms + - "vms/*" + verbs: + - list + - get + - create + - update + - patch + - delete + - resources: + - disks + resourceNames: + - "*" + verbs: + - list + - resources: + - "experiments/files" + verbs: + - create + - resources: + - hosts + resourceNames: + - "*" + verbs: + - list + - resources: + - builder + verbs: + - get + - post + - put + # Start and cancel Scorch runs. Typing into Scorch terminals needs the + # separate scorch/terminals write permission, which this role does not have. + - resources: + - scorch + verbs: + - get + - post + - delete + - resources: + - tunneler + verbs: + - get +``` + +#### Experiment User (`experiment-user`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: experiment-user +spec: + roleName: Experiment User + policies: + - resources: + - experiments + - "experiments/*" + verbs: + - list + - get + - resources: + - vms + - "vms/*" + verbs: + - list + - get + - patch + - resources: + - "vms/redeploy" + verbs: + - update + - resources: + - "vms/captures" + verbs: + - create + - delete + - resources: + - "vms/snapshots" + verbs: + - list + - create + - update + # Tunneler port forwards. Keep this before the first policy with + # resourceNames so assigning the role scopes it to the user's VMs. + - resources: + - "vms/forwards" + verbs: + - create + - delete + - resources: + - "experiments/files" + verbs: + - create + - resources: + - hosts + resourceNames: + - "*" + verbs: + - list + - resources: + - builder + verbs: + - get + - post + # Start and cancel Scorch runs. Typing into Scorch terminals needs the + # separate scorch/terminals write permission, which this role does not have. + - resources: + - scorch + verbs: + - get + - post + - delete + - resources: + - tunneler + verbs: + - get +``` + +#### Experiment Viewer (`experiment-viewer`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: experiment-viewer +spec: + roleName: Experiment Viewer + policies: + - resources: + - experiments + - "experiments/*" + - vms + - "vms/*" + verbs: + - list + - get + # Keep this before the first policy with resourceNames so assigning the role + # scopes it to the user's VMs. + - resources: + - "vms/mount" + verbs: + - post + - delete + - resources: + - hosts + resourceNames: + - "*" + verbs: + - list + - resources: + - builder + verbs: + - get + - resources: + - scorch + verbs: + - get + - resources: + - tunneler + verbs: + - get +``` + +#### VM Admin (`vm-admin`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: vm-admin +spec: + roleName: VM Admin + policies: + - resources: + - experiments + - experiments/* + verbs: + - list + - get + - resources: + - vms + - vms/* + verbs: + - '*' + # Start and cancel Scorch runs. Typing into Scorch terminals needs the + # separate scorch/terminals write permission, which this role does not have. + - resources: + - scorch + verbs: + - get + - post + - delete + - resources: + - tunneler + verbs: + - get +``` + +#### VM Viewer (`vm-viewer`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: vm-viewer +spec: + roleName: VM Viewer + policies: + - resources: + - vms + verbs: + - list + - resources: + - "vms/screenshot" + - "vms/vnc" + verbs: + - get + - resources: + - "vms/mount" + verbs: + - post + - list + - delete + - get + - resources: + - builder + verbs: + - get +``` + +#### Scorch Viewer (`scorch-viewer`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: scorch-viewer +spec: + roleName: Scorch Viewer + # View Scorch pipelines, component output, read-only Scorch terminals, and + # the run files Scorch writes to the experiment files directory. Assigning + # the role scopes it to the user's experiments. + policies: + - resources: + - experiments + verbs: + - list + - get + - resources: + - "experiments/apps" + - "experiments/files" + verbs: + - list + - get + - resources: + - scorch + verbs: + - get + - resources: + - builder + verbs: + - get +``` + +#### Scorch Admin (`scorch-admin`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: scorch-admin +spec: + roleName: Scorch Admin + # Everything Scorch Viewer can do, plus start and cancel Scorch runs, type + # into and exit Scorch terminals, and watch the VMs Scorch components act on. + # Assigning the role scopes it to the user's experiments. + policies: + - resources: + - experiments + verbs: + - list + - get + - resources: + - "experiments/apps" + - "experiments/files" + verbs: + - list + - get + - resources: + - vms + verbs: + - list + - get + - resources: + - "vms/screenshot" + verbs: + - get + - resources: + - scorch + verbs: + - "*" + # Type into and exit Scorch terminals. This is separate from scorch because a + # Scorch terminal, such as the one a break component opens, is a shell running + # as the phenix server process, usually as root in a privileged container. + # Anyone with this permission controls the phenix server and can bypass RBAC, + # so only assign this role to users trusted with that access. + - resources: + - "scorch/terminals" + verbs: + - write +``` + +#### Builder (`builder`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: builder +spec: + roleName: Builder + # Design topologies and scenarios in the Builder or on the Configs page, and + # create or update experiments from them. Every policy names its resources, + # so, like the global roles, assigning this role does not scope it to + # experiments. Config access excludes User and Role configs, which would let + # a user grant themselves more access, and Image configs, whose build scripts + # administrators run as root. + policies: + - resources: + - builder + resourceNames: + - "*" + verbs: + - get + - post + - put + - resources: + - configs + resourceNames: + - "Topology/*" + - "Scenario/*" + - "Experiment/*" + verbs: + - list + - get + - create + - update + # create and update are what the Builder needs to create or update an + # experiment; they do not allow starting, stopping, or deleting experiments. + - resources: + - experiments + resourceNames: + - "*" + verbs: + - list + - get + - create + - update + - resources: + - disks + resourceNames: + - "*" + verbs: + - list + - get + - resources: + - topologies + - scenarios + - applications + - hosts + - options + resourceNames: + - "*" + verbs: + - list + - resources: + - schemas + resourceNames: + - "*" + verbs: + - get +``` + +#### Disabled (`disabled`) + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: disabled +spec: + roleName: Disabled + policies: [] +``` + +## Custom Roles + +A custom role is a `Role` config. Create it from the `Configs` tab, or from a +file with `phenix config create `, and then assign it to users on the +`Users` tab. `roleName` is the name shown in the UI; `metadata.name` can also +be used to refer to the role, for example in [`ui.users`](user-administration.md#from-configuration-uiusers). + +This example lets a user run Scorch for their experiments without typing into +Scorch terminals: + +```yaml +apiVersion: phenix.sandia.gov/v1 +kind: Role +metadata: + name: scorch-operator +spec: + roleName: Scorch Operator + policies: + - resources: + - experiments + - "experiments/apps" + - "experiments/files" + verbs: + - list + - get + - resources: + - scorch + verbs: + - get + - post + - delete +``` + +When writing a custom role: + +* Put policies that should be limited to the user's experiments first, before + any policy that sets `resourceNames`. See + [Scoping a Role to Experiments](#scoping-a-role-to-experiments). +* `configs` names are `/`, so use patterns such as `Topology/*`, + not `*`. +* Only grant these to roles meant to administer phēnix, because each lets a + user gain more access: + * `configs` `create` or `update` on `User/*` or `Role/*`. + * `users` `create`, [`users/tokens`](#resource-userstokens) `create`, and + `users/roles` `patch`. + * [`scorch/terminals`](#resource-scorchterminals) and + [`miniconsole`](#resource-miniconsole). +* Existing users keep their copy of a role until it is reassigned; see + [How Permissions Are Checked](#how-permissions-are-checked). + +## Resources + +Each table lists a resource's verbs, what they allow, and what the check is +named with (see [Named and unnamed checks](#how-permissions-are-checked)). +"—" means the check is not named, so `resourceNames` don't limit it. + +### Experiments + +#### Resource: `experiments` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list experiments; the list shows only experiments the user can access by name, and includes each experiment's VMs | experiment | +| get | view an experiment and its VMs (VMs are filtered by [`vms`](#resource-vms) `list`), see live updates when an experiment is created, and read its [Scorch](#resource-scorch) data | experiment | +| create | create an experiment, including from the Builder | — | +| update | update an experiment's topology from the Builder (also needs [`builder`](#resource-builder) `put`) | experiment | +| patch | change the VLAN aliases of a stopped experiment | experiment | +| delete | delete an experiment | experiment | + +#### Resource: `experiments/apps` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | see an experiment's apps and which are running; the Scorch table needs this | experiment | + +#### Resource: `experiments/captures` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list an experiment's packet captures; the list shows only captures for VMs the user can access by name | experiment, then experiment/VM | + +#### Resource: `experiments/files` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list an experiment's files, including Scorch run output | experiment | +| get | download an experiment file, or copy it into a mounted VM disk (also needs [`vms/mount`](#resource-vmsmount) `patch`) | experiment | +| create | upload experiment files through the file server | experiment | + +#### Resource: `experiments/netflow` + +| Verb | Allows | Named with | +|--------|--------|------------| +| get | check whether netflow is capturing, and stream netflow data | experiment | +| create | start a netflow capture | experiment | +| delete | stop a netflow capture | experiment | + +#### Resource: `experiments/schedule` + +| Verb | Allows | Named with | +|--------|--------|------------| +| get | view the experiment's VM-to-host schedule | experiment | +| create | schedule an experiment with a scheduling algorithm | experiment | + +#### Resource: `experiments/start` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | start an experiment, and see live start progress and errors | experiment | + +#### Resource: `experiments/stop` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | stop an experiment, and see live stop progress and errors | experiment | + +#### Resource: `experiments/topology` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | view and search the experiment's topology graph | experiment | + +#### Resource: `experiments/trigger` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | trigger the running stage of an experiment's apps, and see live app trigger updates; triggering the Scorch app also needs [`scorch`](#resource-scorch) `post` | experiment | +| delete | cancel triggered apps; canceling the Scorch app also needs [`scorch`](#resource-scorch) `delete` | experiment | + +Starting and canceling Scorch runs from the Scorch table does not need +`experiments/trigger`. + +#### Resource: `exp/captureSubnet` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | start or stop packet captures on every VM interface in a subnet | experiment | + +This resource starts with `exp/`, so `experiments/*` does not grant it. Of the +built-in roles, only Global Admin has it. + +### VMs + +VM checks are named `/`. + +#### Resource: `vms` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list VMs, including their screenshots and live screenshot updates; the list shows only VMs the user can access by name | experiment/VM | +| list | view an experiment's state of health | — | +| get | view a VM | experiment/VM | +| patch | change a VM's settings, such as CPUs, memory, disk, VLANs, tags, boot, host, and snapshot; bulk edits skip VMs the user can't access | experiment/VM | +| delete | kill a VM in a running experiment | experiment/VM | + +#### Resource: `vms/captures` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list a VM's packet captures | experiment/VM | +| create | start a packet capture on a VM interface | experiment/VM | +| delete | stop a VM's packet captures | experiment/VM | + +#### Resource: `vms/cdrom` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | insert an ISO into a VM's CD-ROM drive | experiment/VM | +| delete | eject a VM's CD-ROM | experiment/VM | + +#### Resource: `vms/commit` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | create a new backing image from a VM | experiment/VM | + +#### Resource: `vms/forwards` + +Port forwards are used by the [tunneler](tunneler.md). + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list a VM's port forwards, including other users' | experiment/VM | +| get | connect through any user's port forward | experiment/VM | +| create | create a port forward | experiment/VM | +| delete | delete your own port forward | experiment/VM | + +#### Resource: `vms/memorySnapshot` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | create an ELF memory dump of a VM | experiment/VM | + +#### Resource: `vms/mount` + +Only available when phēnix is started with the `vm-mount` feature. + +| Verb | Allows | Named with | +|--------|--------|------------| +| post | mount a VM's disk on the headnode | experiment/VM | +| delete | unmount it | experiment/VM | +| list | browse the mounted files | experiment/VM | +| get | download a mounted file | experiment/VM | +| patch | upload a file into the mount, or copy an experiment file into it (also needs [`experiments/files`](#resource-experimentsfiles) `get`) | experiment/VM | + +#### Resource: `vms/redeploy` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | redeploy a VM | experiment/VM | + +#### Resource: `vms/reset` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | reset a VM's disk state | experiment/VM | + +#### Resource: `vms/restart` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | restart a VM | experiment/VM | + +#### Resource: `vms/screenshot` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | get a VM's screenshot | experiment/VM | + +VM lists that include screenshots only need [`vms`](#resource-vms) `list`. + +#### Resource: `vms/shutdown` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | shut down a VM | experiment/VM | + +#### Resource: `vms/snapshots` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list a VM's snapshots | experiment/VM | +| create | snapshot a VM, and see live snapshot and restore progress | experiment/VM | +| update | restore a VM to a snapshot | experiment/VM | + +#### Resource: `vms/start` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | start or resume a VM | experiment/VM | + +#### Resource: `vms/stop` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | pause (stop) a VM | experiment/VM | + +#### Resource: `vms/vnc` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | open a VM's VNC console | experiment/VM | + +### Configs and Experiment Design + +#### Resource: `configs` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list configs, and see live config changes | `/` | +| list | load a Builder topology into the Builder (also needs [`builder`](#resource-builder) `get`) | `Topology/` | +| get | view or download a config | `/` | +| create | create a config from the `Configs` tab, the API, or the workflow API, or rename a config or change its kind | `/` of the new config | +| update | edit a config, including through the workflow API | `/` | +| delete | delete a config | `/` | + +Config names are the config's kind and name, such as `Topology/foo`. A +resource name of `*` does not match any config; use `*/*` for all configs or a +kind pattern such as `Topology/*`. + +!!! warning + `configs` `create` or `update` access to `User/*` or `Role/*` lets a user + create and change users and roles, and so gain more access. The Builder + role only covers `Topology/*`, `Scenario/*`, and `Experiment/*`. + +The configs API never returns the password hashes and API tokens stored in +User configs, and updating a User config through it keeps the stored ones. + +#### Resource: `topologies` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list topologies, including the Builder's topology list | topology | + +#### Resource: `scenarios` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list the scenarios for a topology | scenario | + +#### Resource: `applications` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list the available phēnix apps | app | + +#### Resource: `schemas` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | get config schemas, used to validate configs in the UI | config kind, when getting one kind | + +#### Resource: `options` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | get server defaults used when creating experiments, such as bridge mode | — | + +#### Resource: `disks` + +Disk checks are named with the image's file name, such as `ubuntu.qc2`. + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list disk images (VM, ISO, and container images) | file name | +| get | download a disk image | file name | +| create | snapshot a disk into a new image | new file name | +| create | clone a disk | — | +| update | commit a disk into its backing image (checked on both), or rebase, resize, or rename a disk | file name | +| delete | delete a disk image | file name | +| upload | upload a disk image | — | + +#### Resource: `workflow` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | apply a [git workflow](git-workflow.md), which creates, updates, and restarts experiments | — | + +The workflow config API uses [`configs`](#resource-configs) permissions +instead. + +### Builder, Scorch, and Tunneler + +#### Resource: `builder` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | open the Builder, list and load Builder topologies (also needs [`configs`](#resource-configs) `list`), and save topology files locally | — | +| post | create an experiment and its topology from the Builder (also needs [`experiments`](#resource-experiments) `create`) | — | +| put | update an experiment's topology from the Builder (also needs [`experiments`](#resource-experiments) `update` for the experiment, and `create` if it doesn't exist) | — | + +#### Resource: `scorch` + +Every Scorch route also needs [`experiments`](#resource-experiments) `get` +for the experiment. Triggering the Scorch app through +[`experiments/trigger`](#resource-experimentstrigger) needs `scorch` `post` or +`delete` instead. + +| Verb | Allows | Named with | +|--------|--------|------------| +| get | view Scorch pipelines, component output, and read-only Scorch terminals, and see live Scorch updates | — | +| post | start a Scorch run | — | +| delete | cancel a Scorch run | — | + +#### Resource: `scorch/terminals` + +| Verb | Allows | Named with | +|-------|--------|------------| +| write | type into and exit Scorch terminals (also needs [`scorch`](#resource-scorch) `get`) | — | + +!!! warning + A Scorch terminal is a shell on the phēnix server, so this permission + gives control of the phēnix server. It is separate from + [`scorch`](#resource-scorch) so that users can run Scorch without it. See + [Builder, Scorch, and Tunneler Access](#builder-scorch-and-tunneler-access). + `*` and `scorch` don't match `scorch/terminals`, so `scorch` with verb + `*` does not grant it; patterns such as `*/*` and `scorch/*` do. + +#### Resource: `tunneler` + +Only available when phēnix serves tunneler downloads, which it does when a +`downloads/tunneler` directory exists in its working directory, as in the +Docker image. + +| Verb | Allows | Named with | +|------|--------|------------| +| get | download the phēnix [tunneler](tunneler.md) (creating port forwards needs [`vms/forwards`](#resource-vmsforwards)) | — | + +### Users and System + +#### Resource: `users` + +| Verb | Allows | Named with | +|--------|--------|------------| +| list | list users; without it, the list shows only the requester (with `get`) | username | +| get | view a user | username | +| create | create users, and see live updates when users are created | — | +| patch | change a user's name and password, and create API tokens for the user if it's the requester (tokens for other users also need [`users/tokens`](#resource-userstokens)) | username | +| delete | delete a user (users can't delete themselves) | username | + +Users created from the `Users` tab or API get `get` and `patch` for +themselves, so they can change their own password and create their own API +tokens. Users created from [`ui.users`](user-administration.md#from-configuration-uiusers) +only get `get`. + +#### Resource: `users/tokens` + +| Verb | Allows | Named with | +|--------|--------|------------| +| create | create API tokens for another user (also needs [`users`](#resource-users) `patch`) | username | + +A token for another user lets the holder act as that user. Of the built-in +roles, only Global Admin has this permission. + +#### Resource: `users/roles` + +| Verb | Allows | Named with | +|-------|--------|------------| +| patch | change a user's role and resource names (also needs [`users`](#resource-users) `patch`); without it, role changes are ignored | username | + +#### Resource: `roles` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list roles, such as for the role menu on the `Users` tab | — | + +#### Resource: `hosts` + +| Verb | Allows | Named with | +|------|--------|------------| +| list | list minimega cluster hosts | host | + +#### Resource: `logs` + +| Verb | Allows | Named with | +|------|--------|------------| +| get | view phēnix and minimega logs on the `Logs` tab, and receive live log messages | — | + +#### Resource: `miniconsole` + +Only available when phēnix is started with `--minimega-console`. + +| Verb | Allows | Named with | +|------|--------|------------| +| post | open and resize a minimega console | — | +| get | attach to a minimega console, with read and write access | — | + +!!! warning + A minimega console can run any minimega command on the cluster, so this + permission gives control of every experiment and cluster host. Treat it + like [`scorch/terminals`](#resource-scorchterminals). + +#### Resource: `settings` + +| Verb | Allows | Named with | +|--------|--------|------------| +| update | change phēnix settings on the `Settings` tab; viewing settings needs no permission | — | diff --git a/docs/scorch.md b/docs/scorch.md index 6a7f9df..ee4d387 100644 --- a/docs/scorch.md +++ b/docs/scorch.md @@ -6,6 +6,19 @@ A phēnix [scenario](configuration.md#scenario) configuration file is used to de The screenshots and [configuration file](#example-configuration) in the rest of this document are from an example Scorch scenario, `scorch-demo`. +## Access Control + +When authentication is enabled, Scorch uses these [permissions](roles-and-permissions.md#resources): + +- [`scorch`](roles-and-permissions.md#resource-scorch) `get` to view Scorch pipelines, component output, and read-only terminals. +- `scorch` `post` and `delete` to start and cancel Scorch runs. +- [`scorch/terminals`](roles-and-permissions.md#resource-scorchterminals) `write` to type into and exit Scorch terminals. + +All of these also need read access to the experiment. The built-in [Scorch Viewer and Scorch Admin](roles-and-permissions.md#builder-scorch-and-tunneler-access) roles cover viewing and running Scorch. + +!!! warning + A Scorch terminal, such as the one a [`break`](#break-component) component opens, is a shell running as the phēnix server process. Anyone who can type into it can control the phēnix server and bypass phēnix access control. That is why typing into Scorch terminals is a separate permission, which only Global Admin and Scorch Admin have by default. + ## Scorch Components A Scorch component is simply an executable available to be called by the Scorch app within phēnix. A component is expected to implement any or all of the various [stages](#stages) in the [Scorch pipeline](#scorch-pipeline). @@ -49,7 +62,7 @@ The following Scorch component types are considered `core` components, in that t ### `break` Component -The `break` component is comparable to a source code break point when debugging an application in that it pauses execution of the current Scorch run until a user exits the break. While the `break` component is running, users have access to a shell on the server running phēnix as the user running phēnix. The first user to access the shell via the terminal modal in the UI will have read-write access. If other users access the shell, they will have read-only access but will get live updates as the user with read-write access uses the terminal. +The `break` component is comparable to a source code break point when debugging an application in that it pauses execution of the current Scorch run until a user exits the break. While the `break` component is running, users have access to a shell on the server running phēnix as the user running phēnix. The first user with the [`scorch/terminals`](roles-and-permissions.md#resource-scorchterminals) `write` permission to access the shell via the terminal modal in the UI will have read-write access. Other users, and users without that permission, will have read-only access but will get live updates as the user with read-write access uses the terminal. A run paused at a `break` component continues when a user with read-write access exits the terminal, or when a user with `scorch` `delete` cancels the run. It's possible to configure the `break` component in the Scorch app configuration to create a minimega tap when the component is executed. When the component is executed, the tap will be deleted. In addition to the tap, external network access can also be configured (e.g., Internet access). @@ -296,7 +309,7 @@ The Scorch table, accessible as one of the tab selections within the phēnix UI, - Experiment name - Experiment status: this reports on the status of the experiment — an experiment must be running for a Scorch app to start - Scorch app status: this will report the running or stopped status of the Scorch app itself -- Terminal: if the Scorch app has reached a break point, a terminal will be available — if clicked, a terminal dialog will be opened and is running on the phēnix host system +- Terminal: if the Scorch app has reached a break point, a terminal will be available — if clicked, a terminal dialog will be opened and is running on the phēnix host system (typing into it needs [`scorch/terminals`](roles-and-permissions.md#resource-scorchterminals) `write`) - Find an Experiment: similar to the search fields in other tables within the phēnix UI, it is possible to filter experiment names based on terms entered here ![Scorch Table](images/table.png) diff --git a/docs/tunneler.md b/docs/tunneler.md index 6baeb43..075b2df 100644 --- a/docs/tunneler.md +++ b/docs/tunneler.md @@ -37,6 +37,14 @@ executable (on Linux/MacOS, `chmod +x phenix-tunneler--`). `downloads/tunneler` directory must exist alongside the phēnix binary on the server). This will be the case if you have a typical deployment using the Docker image. +!!! note + When authentication is enabled, the `Tunneler` tab and downloads need the + [`tunneler`](roles-and-permissions.md#resource-tunneler) `get` permission, + and creating a port forward needs + [`vms/forwards`](roles-and-permissions.md#resource-vmsforwards) `create` + for the VM. The built-in Experiment Admin, Experiment User, and VM Admin + roles have both. + ## Starting the Tunneler Server Once downloaded, start the tunneler's local proxy server with the `serve` diff --git a/docs/user-administration.md b/docs/user-administration.md index d8a7c5e..fe4aceb 100644 --- a/docs/user-administration.md +++ b/docs/user-administration.md @@ -1,738 +1,292 @@ -# User Authn/Authz in phenix +# Users and Authentication -`phenix` provides three separate modes of user authentication (authn) and -authorization (authz). +phēnix authenticates users of its web UI and API, and uses role-based access +control (RBAC) to decide what each user can do. This page covers the +authentication modes, creating and managing users, signing in, and API tokens. +What each role and permission allows is described in +[Roles and Permissions](roles-and-permissions.md). -* disabled -* enabled -* proxy +## Authentication Modes -## `disabled` Mode +phēnix has three authentication modes: `disabled`, `enabled`, and `proxy`. The +mode is set in two places, which must agree: -When in `disabled` mode, no user authentication or authorization occurs. Users -do not have to authenticate, and all actions are allowed. +* **The web UI build**, with `VITE_AUTH` set to `disabled`, `enabled`, or + `proxy`. When building the Docker image, set the `PHENIX_WEB_AUTH` build + arg, which defaults to `disabled`. A local UI build (`npm run build` or + `make build`) defaults to `enabled`. The JIT image reads `PHENIX_WEB_AUTH` + when the container starts instead. +* **The `phenix ui` server**, with the JWT signing key. Set it with + `-k/--jwt-signing-key`, the `PHENIX_UI_JWT_SIGNING_KEY` environment + variable, or `ui.jwt-signing-key` in the + [phēnix config file](settings.md#configuration-files). -To use `disabled` mode, the UI should be built with `VUE_APP_AUTH=disabled` (if -Docker is being used to build the UI, use Docker build arg -`PHENIX_WEB_AUTH=disabled`) and the UI server should be started without the -`-k/--jwt-signing-key` option set. +### `disabled` Mode -## `enabled` Mode +No authentication or authorization happens. Users don't sign in, and every +request acts as a Global Admin. -When in `enabled` mode, user authentication and authorization occurs within -phenix directly. Users have to authenticate to the phenix UI, and certain -actions are prohibited based on the role assigned to the user. +Build the UI with `VITE_AUTH=disabled`, and start `phenix ui` without a signing +key in any of the three places above. -To use `enabled` mode, the UI should be built with `VUE_APP_AUTH=enabled` (if -Docker is being used to build the UI, use Docker build arg -`PHENIX_WEB_AUTH=enabled`) and the UI server should be started with the -`-k/--jwt-signing-key` (and optionally the `--jwt-lifetime`) option set. +### `enabled` Mode -## `proxy` Mode +Users sign in to phēnix with a username and password, and their role decides +what they can do. -When in `proxy` mode, user authentication is expected to occur in a reverse -proxy that sits in front of phenix but user authorization still occurs within -phenix directly. Users authenticate to the proxy, and certain actions are -prohibited based on the role assigned to the user. +Build the UI with `VITE_AUTH=enabled`, and start `phenix ui` with a secret +signing key: -To use `proxy` mode, the UI should be built with `VUE_APP_AUTH=proxy` (if Docker -is being used to build the UI, use Docker build arg `PHENIX_WEB_AUTH=proxy`) and -the UI server should be started with the `-k/--jwt-signing-key` and -`--proxy-auth-header` (and optionally the `--jwt-lifetime`) options set. +```shell +phenix ui --jwt-signing-key +``` -In addition, the reverse proxy should add a header to requests being proxied -that contains the username of the authenticated user, with the name of the -header matching what `--proxy-auth-header` is set to (for example, -`--proxy-auth-header=X-phenix-user`). +The key must not be `proxy-jwt` and must not start with `dev|`, because those +values select other modes. -If a user is able to authenticate to the proxy but is not yet a user in phenix, -they will be added as a phenix user automatically and assigned the `Disabled` -role that will deny all actions until an admin user can assign them a different -role. +Signing in gives the user a session token that is valid for `--jwt-lifetime` +(`PHENIX_UI_JWT_LIFETIME`, `ui.jwt-lifetime`), a Go duration that defaults to +`24h`. -## Create a new user +### `proxy` Mode -There are three primary ways to create new users. +A reverse proxy in front of phēnix authenticates users, and phēnix still +decides what each user can do. Build the UI with `VITE_AUTH=proxy`. The server +supports two setups: -1. Choose the `Create Account` link off the login page and complete all fields - in the `Create a New Account` dialogue. This will initiate a message to an - administrator's account who can then activate the account, setting the - role(s) and resource name(s). +* **Username header.** Start `phenix ui` with a secret signing key and + `--proxy-auth-header
` (`PHENIX_UI_PROXY_AUTH_HEADER`), for example + `--proxy-auth-header X-phenix-user`. The proxy adds that header, containing + the authenticated username, to every request. phēnix trusts the header: the + UI signs the user in without a password, and every API request must carry + the header with the same username as its token. +* **Proxy-issued token.** Start `phenix ui` with `--jwt-signing-key proxy-jwt`. + The proxy sends a JWT for the user as `X-Phenix-Auth-Token: Bearer `, + and phēnix reads the username from its `sub`, `username`, or `user` claim. + phēnix does not verify the token's signature. A token is accepted only after + it has been registered by calling `GET /api/v1/login` with it, which the UI + does when it signs in; scripts must do the same. phēnix keeps one + proxy-issued token per user. - ![screenshot](images/login_create.png){: width=400 .center} +!!! warning + In `proxy` mode, phēnix trusts the proxy completely. Make sure clients can + only reach phēnix through the proxy, and that the proxy removes any + username header or `X-Phenix-Auth-Token` header sent by the client. - ![screenshot](images/create_new_account.png){: width=400 .center} +Each proxy user needs a phēnix user with the same username. Create them ahead +of time, as described in [Creating Users](#creating-users); their passwords are +not used in `proxy` mode. A user without a phēnix account is sent to a sign-up +form, but that form sends no password and so fails the +[password requirements](#password-requirements). -2. From the `Users` tab, click the `+` button to create a new user. Here the - administrator will add the [role(s) and resource - name(s)](#user-administration). +In `proxy` mode, the UI header shows `Reauthorize` instead of `Logout`. - ![screenshot](images/create_a_new_user.png){: width=400 .center} +## The First Administrator -3. Create a YAML or JSON file at `/etc/phenix/users.[yml|json]` with the - following structure. When the `phenix` UI starts, it looks for this file and - adds any users present in the file that are not already present in `phenix`. - For users in the file that already exist, `phenix` ensures the user role - matches what's in the file and updates it as necessary. This file is also - automatically watched, so any users added to the file while `phenix` is - running will automatically be added to `phenix`. +If no users are configured in [`ui.users`](#from-configuration-uiusers), +`phenix ui` creates a Global Admin user named `admin@foo.com` with the password +`foobar` when it starts. -```yaml -ui: - users: - - :: - - ... -``` +!!! warning + Configure your own administrator in `ui.users` before exposing phēnix. If + `admin@foo.com` was already created, delete it from the `Users` tab after + signing in as your own administrator. -## Login +## Creating Users -The login page is self-descriptive. Using the `Remember me` checkbox will set a -token to local storage so that you can remove the requirement to enter a -`Username` and `Password` each time the page or site is reloaded. +Every user has exactly one role, and a user with an unknown role is never +created. phēnix can create users in three ways. -If an administrator starts the UI server with the following command, -authentication is enabled: +### From the Users Tab -```shell -phenix ui -k -``` +A user with the `users` `create` permission can click the `+` button on the +`Users` tab and fill in: -Without the `-k` (or `--jwt-signing-key`), authentication is disabled. +* `User Name`, `First Name`, `Last Name`, `Password`, and `Confirm Password`. + The password must meet the [password requirements](#password-requirements). +* `Role`: the user's role. See [Built-In Roles](roles-and-permissions.md#built-in-roles). +* `Resource Name(s)`: optional, space-separated names that limit the role to + certain experiments. See + [Scoping a Role to Experiments](roles-and-permissions.md#scoping-a-role-to-experiments). -## Generating User Authentication Tokens +![screenshot](images/create_a_new_user.png){: width=400 .center} -From the `Users` tab, click the key icon next to the given user's name. A dialog -box will pop up where you can enter in a description for the token to be created -and an expiration date. This expiration date should be entered in Golang time -duration. For example, `4320h` is valid and represents 4320 hours or about 6 -months. After clicking `Create Token` a token should appear with the expiration -date. +The same can be done with the API: `POST /api/v1/users` with `username`, +`password`, `first_name`, `last_name`, `role_name`, and `resource_names`. +Creating a user with a role that doesn't exist returns an error, and creating +a user whose name is taken returns `409 Conflict`. -This token can be used to authenticate when using the Phenix API. Specifically, you would include the following as a header in HTTP requests. +### From Configuration (`ui.users`) -```http -X-phenix-auth-token: ****** -``` +When `phenix ui` starts, it creates the users listed in the `ui.users` +setting. Each entry has this format: -## User Administration - -### Updating Users - -An administrator is able to click on the username on the table in the Users tab -to update a user. They can update `First Name` or `Last Name`, `Role`, -`Experiment Names`, and `Resource Name(s)`. - -### Roles - -`Global Admin` is the administrator level account and has access to all -capabilities, to include user management. Global Admins also have access to all -resources. The following table provides a high-level overview of all the -available roles and their access rights. - -| Role | Limits | List | Get | Create | Update | Patch | Delete | -|-------------------|:-------------------------------------------------------------------------------------------------------------------------|:-----:|:-----:|:------:|:------:|:-----:|:------:| -| Global Admin | Can see and control absolutely anything/everything. | E V U | E V U | E V U | E V U | E V U | E V U | -| Global Viewer | Can see absolutely anything/everything, but cannot make any changes. | E V U | E V U | | | | | -| Experiment Admin | Can see and control anything/everything for assigned experiments, including VMs, but cannot create new experiments. | E V | E V | V | E V | V | V | -| Experiment User | Can see assigned experiments, and can control VMs within assigned experiments, but cannot modify experiments themselves. | E V | E V | | | V | | -| Experiment Viewer | Can see assigned experiments and VMs within assigned experiments, but cannot modify or control experiments or VMs. | E V | E V | | | | | -| VM Admin | Can see assigned experiments, and has full administrative control over VMs in assigned experiments. | E V | E V | V | V | V | V | -| VM Viewer | Can only see VM screenshots and access VM VNC, nothing else. | V | | | | | | - -Key: E - experiment resource, V - VM resource, U - user resource - -### Resources - -#### Resource: `experiments` - -| | | -|------|------| -| Verb | list | -| Desc | get a list of all experiments | -| Exp. Scoped | yes (list is filtered to only include experiments in scope) | -| Res. Scoped | no | - -| | | -|------|------| -| Verb | get -| Desc | get a specific experiment -| Exp. Scoped | yes -| Res. Scoped | no - -| | | -|------|------| -| Verb | create -| Desc | create a new experiment -| Exp. Scoped | no -| Res. Scoped | no - -| | | -|------|------| -| Verb | delete -| Desc | delete a specific experiment -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `experiments/start` - -| | | -|------|------| -| Verb | update -| Desc | start an experiment -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `experiments/stop` - -| | | -|------|------| -| Verb | update -| Desc | stop an experiment -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `experiments/schedule` - -| | | -|------|------| -| Verb | get -| Desc | get current schedule for an experiment -| Exp. Scoped | yes -| Res. Scoped | no - -| | | -|------|------| -| Verb | create -| Desc | schedule an experiment using schedule algorithm -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `experiments/trigger` - -| | | -|------|------| -| Verb | create -| Desc | trigger the running stage of an experiment -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `experiments/captures` - -| | | -|------|------| -| Verb | list -| Desc | get list of packet captures for an experiment -| Exp. Scoped | yes (list is filtered to only include experiments in scope) -| Res. Scoped | yes (list is filtered to only include VMs in scope) - -#### Resource: `experiments/files` - -| | | -|------|------| -| Verb | list -| Desc | get list of files for an experiment -| Exp. Scoped | yes (list is filtered to only include experiments in scope) -| Res. Scoped | no - -| | | -|------|------| -| Verb | get -| Desc | get specific experiment file -| Exp. Scoped | yes -| Res. Scoped | no - -#### Resource: `vms` - -| | | -|------|------| -| Verb | list -| Desc | get list of VMs for an experiment -| Exp. Scoped | yes (list is filtered to only include experiments in scope) -| Res. Scoped | yes (list is filtered to only include VMs in scope) - -| | | -|------|------| -| Verb | get -| Desc | get a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | patch -| Desc | update a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | delete -| Desc | delete a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/start` - -| | | -|------|------| -| Verb | update -| Desc | start a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/stop` - -| | | -|------|------| -| Verb | update -| Desc | stop a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/redeploy` - -| | | -|------|------| -| Verb | update -| Desc | redeploy a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/screenshot` - -| | | -|------|------| -| Verb | get -| Desc | get screenshot for a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/vnc` - -| | | -|------|------| -| Verb | get -| Desc | get VNC address for a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/captures` - -| | | -|------|------| -| Verb | list -| Desc | get list of packet captures for a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | create -| Desc | start a packet capture on a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | delete -| Desc | stop all packet captures on a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/snapshots` - -| | | -|------|------| -| Verb | list -| Desc | get list of snapshots for a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | create -| Desc | create a snapshot of a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -| | | -|------|------| -| Verb | update -| Desc | restore a specific experiment VM to a previous snapshot -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/commit` - -| | | -|------|------| -| Verb | create -| Desc | create a new backing image from a specific experiment VM -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `applications` - -| | | -|------|------| -| Verb | list -| Desc | get list of user applications -| Exp. Scoped | no -| Res. Scoped | yes (list is filtered to only include applications in scope) - -#### Resource: `topologies` - -| | | -|------|------| -| Verb | list -| Desc | get list of available topologies -| Exp. Scoped | no -| Res. Scoped | yes (list is filtered to only include topologies in scope) - -#### Resource: `disks` - -| | | -|------|------| -| Verb | list -| Desc | get list of available backing images -| Exp. Scoped | no -| Res. Scoped | yes (list is filtered to only include backing images in scope) - -#### Resource: `hosts` - -| | | -|------|------| -| Verb | list -| Desc | get list of minimega cluster hosts -| Exp. Scoped | no -| Res. Scoped | yes (list is filtered to only include hosts in scope) - -#### Resource: `users` - -| | | -|------|------| -| Verb | list -| Desc | get list of users -| Exp. Scoped | no -| Res. Scoped | yes (list is filtered to only include users in scope) - -| | | -|------|------| -| Verb | get -| Desc | get a specific user -| Exp. Scoped | no -| Res. Scoped | yes - -| | | -|------|------| -| Verb | create -| Desc | create a new user -| Exp. Scoped | no -| Res. Scoped | no - -| | | -|------|------| -| Verb | patch -| Desc | update an existing user -| Exp. Scoped | no -| Res. Scoped | yes - -| | | -|------|------| -| Verb | delete -| Desc | delete an existing user -| Exp. Scoped | no -| Res. Scoped | yes - -#### Resource: `users/roles` - -| | | -|------|------| -| Verb | patch -| Desc | update user role assignments -| Exp. Scoped | no -| Res. Scoped | yes - -#### Resource: `configs` - -| | | -|------|------| -| Verb | list, get, create, update, delete -| Desc | manage store configurations (topologies, scenarios, etc.) -| Exp. Scoped | no -| Res. Scoped | yes - -#### Resource: `settings` - -| | | -|------|------| -| Verb | update -| Desc | update phēnix system settings -| Exp. Scoped | no -| Res. Scoped | no - -#### Resource: `vms/mount` - -| | | -|------|------| -| Verb | list, get, post, patch, delete -| Desc | manage VM filesystem mounts on headnode -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/forwards` - -| | | -|------|------| -| Verb | list, get, create, delete -| Desc | manage port forwarding rules for experiment VMs -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/cdrom` - -| | | -|------|------| -| Verb | update, delete -| Desc | mount or eject CD-ROM ISO images on experiment VMs -| Exp. Scoped | yes -| Res. Scoped | yes - -#### Resource: `vms/memorySnapshot` - -| | | -|------|------| -| Verb | create -| Desc | create ELF memory dumps of experiment VMs -| Exp. Scoped | yes -| Res. Scoped | yes - -### Built-In Roles - -The following default roles are defined in phēnix as YAML resource specifications: - -#### Global Admin (`global-admin`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: global-admin -spec: - roleName: Global Admin - policies: - - resources: - - "*" - - "*/*" - resourceNames: - - "*" - - "*/*" - verbs: - - "*" +```text +::[:...] ``` -#### Global Viewer (`global-viewer`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: global-viewer -spec: - roleName: Global Viewer - policies: - - resources: - - "*" - - "*/*" - resourceNames: - - "*" - - "*/*" - verbs: - - list - - get - - resources: - - "vms/mount" - resourceNames: - - "*" - - "*/*" - verbs: - - post - - delete -``` +* `` is a role's display name, such as `Experiment User`, or its config + name, such as `experiment-user`. +* Any fields after the role are resource names that limit the role to certain + experiments, for example `alice::Experiment User:exp-a:exp-a/*`. + See [Scoping a Role to Experiments](roles-and-permissions.md#scoping-a-role-to-experiments). + +`ui.users` can be set in any of these places: + +* A `users` config file, such as `users.yml`, in the current directory, + `~/.config/phenix` (when not running as root), or `/etc/phenix`: + + ```yaml + ui: + users: + - admin::Global Admin + - alice::Experiment User:exp-a:exp-a/* + ``` + +* `ui.users` in the [phēnix config file](settings.md#configuration-files). +* The `--users` flag, with entries separated by commas or given by repeating + the flag. +* The `PHENIX_UI_USERS` environment variable, with entries separated by + spaces. Role display names contain spaces, so use config names such as + `global-admin` here. + +These sources don't combine: the `--users` flag wins over `PHENIX_UI_USERS`, +which wins over the config files, and a `users` file overrides `ui.users` in +the phēnix config file. + +phēnix reads `ui.users` only when `phenix ui` starts, so restart it after +changing the list. For each entry: + +* If the user doesn't exist, phēnix creates it. Entries whose role doesn't + exist are skipped and logged. +* If the user exists and its role is not the one listed, phēnix assigns the + listed role and resource names, which undoes role changes made on the + `Users` tab. The comparison uses the role's display name, so an entry that + uses a config name, such as `experiment-user`, reassigns the role and its + resource names at every start. Changing only an entry's resource names does + not update an existing user. +* Passwords of existing users are never changed. + +Passwords in `ui.users` don't have to meet the password requirements and can't +contain `:`. Users created this way can view their own user, but can't change +their own password or create their own API tokens unless their role allows it. + +### Self Sign-Up + +In `enabled` mode, the sign-in page has a `Create Account` button that opens a +`Create a New Account` dialog. It asks for a user name, first name, last name, +and password. + +![screenshot](images/login_create.png){: width=400 .center} + +![screenshot](images/create_new_account.png){: width=400 .center} + +The new account gets the `Disabled` role and is signed in, but can't do +anything until an administrator assigns it a role on the `Users` tab. +phēnix doesn't notify administrators; the new account appears on the `Users` +tab with the `Disabled` role after the page is refreshed. Anyone who can reach +the sign-in page can create a `Disabled` account. + +### Password Requirements + +By default, passwords must be at least 8 characters long and contain a +lowercase letter, a number, and a symbol. Uppercase letters are not required. +Change these under `Settings` > `Password Settings`, which needs the +[`settings`](roles-and-permissions.md#resource-settings) `update` permission. +The minimum length can be set from 8 to 32. + +The requirements apply to users created from the `Users` tab, the API, and self +sign-up, and to password changes. They don't apply to users created from +`ui.users`. + +## Signing In + +Sign in on the phēnix sign-in page with a username and password. + +* `Remember me` keeps the session in the browser's local storage, so it + survives new tabs and browser restarts. Without it, the session lasts only + in the current tab. +* The session ends when its token expires (`--jwt-lifetime`, `24h` by + default), and the UI asks the user to sign in again. +* `Logout` in the header ends the session and revokes its token on the server. +* phēnix can also sign out idle users; see + [Web UI Session Timeout](settings.md#web-ui-session-timeout). + +To sign in from a script, call `POST /api/v1/login` with a JSON body of +`{"user": "", "pass": ""}`, or `GET /api/v1/login` with +HTTP basic authentication. The response's `token` is valid for +`--jwt-lifetime`: -#### Experiment Admin (`experiment-admin`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: experiment-admin -spec: - roleName: Experiment Admin - policies: - - resources: - - experiments - - "experiments/*" - verbs: - - list - - get - - update - - resources: - - vms - - "vms/*" - verbs: - - list - - get - - create - - update - - patch - - delete - - resources: - - disks - resourceNames: - - "*" - verbs: - - list - - resources: - - "experiments/files" - verbs: - - create - - resources: - - hosts - resourceNames: - - "*" - verbs: - - list -``` +```shell +TOKEN=$(curl -s -X POST -d '{"user":"alice","pass":""}' \ + https://phenix.example.com/api/v1/login | jq -r .token) -#### Experiment User (`experiment-user`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: experiment-user -spec: - roleName: Experiment User - policies: - - resources: - - experiments - - "experiments/*" - verbs: - - list - - get - - resources: - - vms - - "vms/*" - verbs: - - list - - get - - patch - - resources: - - "vms/redeploy" - verbs: - - update - - resources: - - "vms/captures" - verbs: - - create - - delete - - resources: - - "vms/snapshots" - verbs: - - list - - create - - update - - resources: - - "experiments/files" - verbs: - - create - - resources: - - hosts - resourceNames: - - "*" - verbs: - - list +curl -H "X-Phenix-Auth-Token: Bearer $TOKEN" \ + https://phenix.example.com/api/v1/experiments ``` -#### Experiment Viewer (`experiment-viewer`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: experiment-viewer -spec: - roleName: Experiment Viewer - policies: - - resources: - - experiments - - "experiments/*" - - vms - - "vms/*" - verbs: - - list - - get - - resources: - - hosts - resourceNames: - - "*" - verbs: - - list - - resources: - - "vms/mount" - verbs: - - post - - delete -``` +## API Tokens -#### VM Admin (`vm-admin`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: vm-admin -spec: - roleName: VM Admin - policies: - - resources: - - experiments - - "experiments/*" - verbs: - - list - - get - - resources: - - vms - - "vms/*" - verbs: - - "*" -``` +For scripts and integrations, create a longer-lived API token: -#### VM Viewer (`vm-viewer`) - -```yaml -apiVersion: phenix.sandia.gov/v1 -kind: Role -metadata: - name: vm-viewer -spec: - roleName: VM Viewer - policies: - - resources: - - vms - verbs: - - list - - resources: - - "vms/screenshot" - - "vms/vnc" - verbs: - - get - - resources: - - "vms/mount" - verbs: - - post - - list - - delete - - get +1. On the `Users` tab, click the key icon (`create new user token`) next to the + user. This needs the [`users`](roles-and-permissions.md#resource-users) + `patch` permission for that user, which users created from the `Users` tab + have for themselves. A token for another user also needs + [`users/tokens`](roles-and-permissions.md#resource-userstokens) `create`, + which only Global Admin has by default. +2. Enter a `Description` and a `Lifetime (days)`. The lifetime is a number of + days, such as `180`, or a Go duration, such as `4320h`. +3. Click `Create Token`. The token and its expiration are shown once, so copy + the token before closing the dialog. + +Send the token in the `X-Phenix-Auth-Token` header, prefixed with `Bearer`: + +```http +X-Phenix-Auth-Token: Bearer ``` + +The header name and `Bearer` are not case-sensitive. A token without the +`Bearer` prefix is rejected with `401 Unauthorized`. In `enabled` mode, where +a header can't be set, such as in a link, the token can be passed as a `token` +query parameter instead. +In `proxy` mode with a username header, API requests also need that header. + +phēnix doesn't show a user's tokens, including through the configs API. To +revoke a token, call `GET /api/v1/logout` with it. Deleting a user revokes all +of the user's tokens, and changing the signing key revokes every token. + +## Managing Users + +### Editing Users + +On the `Users` tab, click a username or its pencil icon to open the +`User ` dialog, which has `First Name`, `Last Name`, `Password`, +`New Password`, `Role`, and `Resource Name(s)`. + +* To change a password, enter the current password in `Password` and the new + one in `New Password`. This is required even for administrators, so to reset + a forgotten password, delete and recreate the user, which also resets its + role and revokes its tokens. +* Changing `Role` and `Resource Name(s)` needs the + [`users/roles`](roles-and-permissions.md#resource-usersroles) `patch` + permission for the user, in addition to `users` `patch`; without it, those + changes are ignored. The UI only shows these fields to users with `users` + `create`, and doesn't let users change their own role. +* A user whose role changes should sign out and back in, because the UI keeps + the role it received at sign in. +* Assigning a role copies the role's current policies into the user, which is + also how changes to a role config reach users who already have it. +* Leaving `First Name` or `Last Name` blank keeps the current value. + +### Deleting Users + +Click the trash icon next to a user to delete it. This needs the +[`users`](roles-and-permissions.md#resource-users) `delete` permission, and +users can't delete themselves. Deleting a user revokes all of the user's API +tokens. + +## Roles and Permissions + +Roles, the permissions they grant, and how to scope them to experiments are +described in [Roles and Permissions](roles-and-permissions.md). diff --git a/mkdocs.yml b/mkdocs.yml index 6964352..1638e06 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -96,6 +96,7 @@ nav: - Git Workflow: git-workflow.md - Administration: - Users: user-administration.md + - Roles and Permissions: roles-and-permissions.md - Reference: - minimega: minimega.md - Troubleshooting: troubleshooting.md