Casvisor
Access control

Permissions

A permission says: these people may do these things on these assets, from these addresses, during this time. Users who are not administrators can only reach an asset when a permission says so.

Administrators manage permissions under Permissions.

Fields

FieldMeaning
Organization, NameLike assets, a permission belongs to one Casdoor organization and applies to its users and assets only.
UsersUsers by name. * means every user of the organization.
GroupsCasdoor groups. Every member is covered.
AssetsAssets by name. * means every asset of the organization.
Asset tagsEvery asset whose Tag is one of these, including assets tagged later.
ActionsAny of Connect, Copy, Paste, Upload, Download.
Client IPsAddresses or CIDR ranges the user must connect from, such as 10.0.0.0/8 or 203.0.113.7. Empty means from anywhere.
Start time, End timeThe window in which the permission counts. Either can be empty, meaning no limit on that side.
EnabledOff means the permission counts for nothing, without deleting it.

A permission covers everyone in Users and everyone in Groups, for every asset in Assets and every asset with a tag in Asset tags.

The actions

ActionWhat it allows
ConnectSeeing the asset in the workbench and opening a session to it. Without it, the other actions give nothing.
CopyText from the remote clipboard reaching the user's browser.
PasteText from the user's clipboard reaching the remote side.
Upload, DownloadReserved for file transfer, which is not in the interface yet.

Protocols lists where Copy and Paste are enforced: by guacd for Telnet and by the web client for VNC. SSH does not restrict them yet, and RDP has no clipboard yet.

How permissions combine

Permissions only ever allow. A user may do an action on an asset when any enabled permission inside its time window covers that user (by name, by * or by group), that asset (by name, by * or by tag), that action, and the address they connect from. There is no deny rule; to take something away, edit or turn off the permission that gives it.

Some examples:

GoalUsers / GroupsAssets / Asset tagsActionsClient IPsTime
The ops team on all Linux servers, from the officegroup opstag linuxConnect, Copy, Paste198.51.100.0/24
A contractor on two servers for a week, no clipboarduser aliceweb-01, web-02Connect2026-11-01 to 2026-11-08
Everyone on the jump desktop*jump-desktopConnect, Paste

When it is checked

Casvisor checks permissions when it lists the assets of a user's workbench, when a session starts, and again when the session's WebSocket opens. Changes therefore apply to the next connection straight away.

A session that is already open is not re-checked, so revoking a permission does not cut off someone connected at that moment. Stop their session under Sessions to do that.

Group membership is read when the user signs in; see When changes in Casdoor take effect.

The client IP

The address checked against Client IPs is the one the connection comes from. When it comes from a loopback or private address, as it does behind a reverse proxy on the same network, Casvisor takes the last entry of X-Forwarded-For instead, which is the address your proxy saw. Make sure the proxy sets that header; see Behind a reverse proxy.

The Casbin model

Casvisor turns the enabled permissions of the organization into a Casbin policy for each request and enforces it with this model:

[request_definition]
r = sub, obj, act, ip

[policy_definition]
p = sub, obj, act, ip

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && r.act == p.act && ipAllowed(r.ip, p.ip)

g puts the user into user:* and into each of their groups, g2 puts each asset into asset:* and its tag, and ipAllowed matches an address against an IP or a CIDR range. Each permission becomes one policy line per user or group, asset or tag, action and address range.

* works for Users and Assets. In Groups and Asset tags it has no special meaning yet; to cover everyone or everything, use * in Users or Assets instead.

Edit on GitHub

On this page