improve documentation
This commit is contained in:
parent
4814e7899c
commit
04a3438182
@ -131,7 +131,7 @@ DO LANGUAGE plpgsql $$
|
|||||||
BEGIN
|
BEGIN
|
||||||
SET hsadminng.currentUser TO '';
|
SET hsadminng.currentUser TO '';
|
||||||
|
|
||||||
FOR t IN 0..69 LOOP
|
FOR t IN 0..6999 LOOP
|
||||||
currentTask = 'creating RBAC test customer #' || t;
|
currentTask = 'creating RBAC test customer #' || t;
|
||||||
SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net';
|
SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net';
|
||||||
SET LOCAL hsadminng.assumedRoles = '';
|
SET LOCAL hsadminng.assumedRoles = '';
|
||||||
|
282
sql/rbac.md
282
sql/rbac.md
@ -141,6 +141,11 @@ An *RbacReference* is a generalization of all entity types which participate in
|
|||||||
|
|
||||||
The primary key of the *RbacReference* and its referred object is always identical.
|
The primary key of the *RbacReference* and its referred object is always identical.
|
||||||
|
|
||||||
|
#### RbacReferenceType
|
||||||
|
|
||||||
|
The enum *RbacReferenceType* describes the type of reference.
|
||||||
|
It's only needed to make it easier to find the referred object in *RbacUser*, *RbacRole* or *RbacPermission*.
|
||||||
|
|
||||||
#### RbacUser
|
#### RbacUser
|
||||||
|
|
||||||
An *RbacUser* is a type of RBAC-subject which references a login account outside this system, identified by a name (usually an email-address).
|
An *RbacUser* is a type of RBAC-subject which references a login account outside this system, identified by a name (usually an email-address).
|
||||||
@ -167,16 +172,17 @@ An *RbacPermission* allows a specific *RbacOperation* on a specific *RbacObject*
|
|||||||
An *RbacOperation* determines, <u>what</u> an *RbacPermission* allows to do.
|
An *RbacOperation* determines, <u>what</u> an *RbacPermission* allows to do.
|
||||||
It can be one of:
|
It can be one of:
|
||||||
|
|
||||||
- **add-...** - permits creating new instances of specific entity types underneath the object specified by the permission, e.g. "add-package"
|
- **'add-...'** - permits creating new instances of specific entity types underneath the object specified by the permission, e.g. "add-package"
|
||||||
- **view** - permits reading the contents of the object specified by the permission
|
- **'view'** - permits reading the contents of the object specified by the permission
|
||||||
- **edit** - change the contents of the object specified by the permission
|
- **'edit'** - change the contents of the object specified by the permission
|
||||||
- **delete** - delete the object specified by the permission
|
- **'delete'** - delete the object specified by the permission
|
||||||
|
- **'\*'**
|
||||||
|
|
||||||
This list is extensible according to the needs of the access rule system.
|
This list is extensible according to the needs of the access rule system.
|
||||||
|
|
||||||
Please notice, that there is no **create-...** operation to create new instances of related business-object-types.
|
Please notice, that there is no **create** operation to create new instances of unrelated business-object-types.
|
||||||
For such a singleton business-object-type, e.g. *Organization" or "Hostsharing" has to be defined, and its single entity is referred in the permission.
|
For such a singleton business-object-type, e.g. *Organization" or "Hostsharing" has to be defined, and its single entity is referred in the permission.
|
||||||
By this, the foreign key in *RbacPermission* can be defined as `NOT NULL`.
|
Only with this rule, the foreign key in *RbacPermission* can be defined as `NOT NULL`.
|
||||||
|
|
||||||
#### RbacGrant
|
#### RbacGrant
|
||||||
|
|
||||||
@ -186,17 +192,51 @@ The core SQL queries to determine access rights are all recursive queries on the
|
|||||||
|
|
||||||
### Role naming
|
### Role naming
|
||||||
|
|
||||||
Automatically generated roles are named as such:
|
The naming pattern of a role is important to be able to address specific roles.
|
||||||
|
E.g. if a new package is added, the admin-role of the related customer has to be addressed.
|
||||||
|
|
||||||
#### business-table#business-object-name.tenant
|
There can be global roles like 'administrators'.
|
||||||
This role is assigned to users who manage objects underneath the object which is accessible through the role.
|
Most roles, though, are specific for certain business-objects and automatically generated as such:
|
||||||
This rule usually gets only view permissions assigned.
|
|
||||||
|
|
||||||
**Example**
|
business-object-table#business-object-name.relative-role
|
||||||
|
|
||||||
'dd'
|
|
||||||
|
|
||||||
## Example Users, Roles, Permissions and Business-Objects
|
Where *business-object-table* is the name of the SQL table of the business object (e.g *customer* or 'package'),
|
||||||
|
*business-object-name* is generated from an immutable business key(e.g. a prefix like 'xyz' or 'xyz00')
|
||||||
|
and the *relative-role*' describes the role relative to the referenced business-object as follows:
|
||||||
|
|
||||||
|
#### owner
|
||||||
|
|
||||||
|
The owner-role is granted to the subject which created the business object.
|
||||||
|
E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...admin'.
|
||||||
|
|
||||||
|
Whoever has the owner-role assigned can do everything with the related business-object, including deleting (or deactivating) it.
|
||||||
|
|
||||||
|
In most cases, the permissions to other operations than 'delete' are granted through the 'admin' role.
|
||||||
|
By this, all roles ob sub-objects, which are assigned to the 'admin' role, are also granted to the 'owner'.
|
||||||
|
|
||||||
|
#### admin
|
||||||
|
|
||||||
|
The admin-role is granted to a role of those subjects who manage the business object.
|
||||||
|
E.g. a 'package' is manged by the admin of the customer.
|
||||||
|
|
||||||
|
Whoever has the admin-role assigned, do everything with the related business-object, including deleting (or deactivating) it.
|
||||||
|
|
||||||
|
In most cases, the permissions to the 'view' operation is granted through the 'tenant' role.
|
||||||
|
By this, all roles ob sub-objects, which are assigned to the 'tenent' role, are also granted to the 'admin'.
|
||||||
|
|
||||||
|
|
||||||
|
#### tenant
|
||||||
|
|
||||||
|
The tenant-role is granted to everybody who needs to be able to view the business-object.
|
||||||
|
Usually all owners, admins and tenants of sub-objects get this role granted.
|
||||||
|
|
||||||
|
Some business-objects only have very limited data directly in the main business-object and store more sensitive data in special sub-objects (e.g. 'customer-details') to which tenants of sub-objects of the main-object (e.g. package admins) do not get view permission.
|
||||||
|
|
||||||
|
|
||||||
|
## Example Users, Roles, Permissions and Business-Objects
|
||||||
|
|
||||||
|
The following diagram shows how users, roles and permissions could be granted access to operations on business objects.
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
@ -270,6 +310,66 @@ PermPackXyz00_AddUser o--> PackXyz00
|
|||||||
@enduml
|
@enduml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Business-Object-Tables, Triggers and Views
|
||||||
|
|
||||||
|
To support the RBAC system, for each business-object-table, some more artifacts are created in the database:
|
||||||
|
|
||||||
|
- a `BEFORE INSERT TRIGGER` which creates the related *RbacObject* instance,
|
||||||
|
- an `AFTER INSERT TRIGGER` which creates the related *RbacRole*s, *RbacPermission*s together with their related *RbacReference*s as well as *RbacGrant*s,
|
||||||
|
- a restricted view (e.g. *customer_rv*) through which restricted users can access the underlying data.
|
||||||
|
|
||||||
|
Not yet implemented, but planned are these actions:
|
||||||
|
|
||||||
|
- an `ON DELETE ... DO INSTEAD` rule to allow `SQL DELETE` if applicable for the business-object-table and the user has 'delete' permission,
|
||||||
|
- an `ON UPDATE ... DO INSTEAD` rule to allow `SQL UPDATE` if the user has 'edit' right,
|
||||||
|
- an `ON INSERT ... DO INSTEAD` rule to allow `SQL INSERT` if the user has 'add-..' right to the parent-business-object.
|
||||||
|
|
||||||
|
The restricted view takes the current user from a session property and applies the hierarchy of its roles all the way down to the permissions related to the respective business-object-table.
|
||||||
|
This way, each user can only view the data they have 'view'-permission for, only create those they have 'add-...'-permission, only update those they have 'edit'- and only delete those they have 'delete'-permission to.
|
||||||
|
|
||||||
|
### Current User
|
||||||
|
|
||||||
|
The current use is taken from the session variable `hsadminng.currentUser` which contains the name of the user as stored in the
|
||||||
|
*RbacUser*s table. Example:
|
||||||
|
|
||||||
|
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
|
||||||
|
|
||||||
|
That user is also used for historicization and audit log, but which is a different topic.
|
||||||
|
|
||||||
|
### Assuming Roles
|
||||||
|
|
||||||
|
If the session variable `hsadminng.assumedRoles` is set to a non-empty value, its content is interpreted as a list of semicolon-separated role names.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
|
||||||
|
|
||||||
|
In this case, not the current user but the assumed roles are used as a starting point for any further queries.
|
||||||
|
Roles which are not granted to the current user, directly or indirectly, cannot be assumed.
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
A full example is shown here:
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
SET SESSION SESSION AUTHORIZATION restricted;
|
||||||
|
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
|
||||||
|
SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
|
||||||
|
|
||||||
|
SELECT c.prefix, p.name as "package", ema.localPart || '@' || dom.name as "email-address"
|
||||||
|
FROM emailaddress_rv ema
|
||||||
|
JOIN domain_rv dom ON dom.uuid = ema.domainuuid
|
||||||
|
JOIN unixuser_rv uu ON uu.uuid = dom.unixuseruuid
|
||||||
|
JOIN package_rv p ON p.uuid = uu.packageuuid
|
||||||
|
JOIN customer_rv c ON c.uuid = p.customeruuid;
|
||||||
|
END TRANSACTION;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Roles and Their Assignments for Certain Business Objects
|
||||||
|
|
||||||
|
To give you an overview of the business-object-types for the following role-examples,
|
||||||
|
check this diagram:
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
@ -282,24 +382,152 @@ hide circle
|
|||||||
' use right-angled line routing
|
' use right-angled line routing
|
||||||
' skinparam linetype ortho
|
' skinparam linetype ortho
|
||||||
|
|
||||||
package rbacPerms {
|
entity EMailAddress
|
||||||
cust
|
|
||||||
}
|
|
||||||
|
|
||||||
package rbacRoles {
|
entity Domain
|
||||||
entity administrators
|
Domain o-- "*" EMailAddress
|
||||||
entity custXXX
|
|
||||||
}
|
|
||||||
|
|
||||||
package rbacUsers {
|
entity UnixUser
|
||||||
entity adminMike
|
UnixUser o-- "*" Domain
|
||||||
adminMike <-- administrators
|
|
||||||
|
|
||||||
entity adminSven
|
entity Package
|
||||||
entity custXXX
|
Package o.. "*" UnixUser
|
||||||
entity pacAdmXXX00
|
|
||||||
}
|
entity Customer
|
||||||
|
Customer o-- "*" Package
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
It's mostly an example hierarchy of business-object-types, but resembles a part of Hostsharing's actual hosting infrastructure.
|
||||||
|
|
||||||
|
The following diagrams show which roles are created for each business-object-type
|
||||||
|
and how they relate to roles from other business-object-types.
|
||||||
|
|
||||||
|
### Customer Roles
|
||||||
|
|
||||||
|
The highest level of the business-object-type-hierarchy is the *Customer*.
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
' left to right direction
|
||||||
|
top to bottom direction
|
||||||
|
|
||||||
|
' hide the ugly E in a circle left to the entity name
|
||||||
|
hide circle
|
||||||
|
|
||||||
|
' use right-angled line routing
|
||||||
|
' skinparam linetype ortho
|
||||||
|
|
||||||
|
entity "BObj customer#xyz" as boCustXyz
|
||||||
|
|
||||||
|
together {
|
||||||
|
entity "Perm customer#xyz *" as permCustomerXyzAll
|
||||||
|
permCustomerXyzAll --> boCustXyz
|
||||||
|
|
||||||
|
entity "Perm customer#xyz add-package" as permCustomerXyzAddPack
|
||||||
|
permCustomerXyzAddPack --> boCustXyz
|
||||||
|
|
||||||
|
entity "Perm customer#xyz view" as permCustomerXyzView
|
||||||
|
permCustomerXyzView --> boCustXyz
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "Role customer#xyz.tenant" as roleCustXyzTenant
|
||||||
|
roleCustXyzTenant --> permCustomerXyzView
|
||||||
|
|
||||||
|
entity "Role customer#xyz.admin" as roleCustXyzAdmin
|
||||||
|
roleCustXyzAdmin --> roleCustXyzTenant
|
||||||
|
roleCustXyzAdmin --> permCustomerXyzAddPack
|
||||||
|
|
||||||
|
entity "Role customer#xyz.owner" as roleCustXyzOwner
|
||||||
|
roleCustXyzOwner ..> roleCustXyzAdmin
|
||||||
|
roleCustXyzOwner --> permCustomerXyzAll
|
||||||
|
|
||||||
|
entity "Role administrators" as roleAdmins
|
||||||
|
roleAdmins --> roleCustXyzOwner
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, there something special:
|
||||||
|
From the 'Role customer#xyz.owner' to the 'Role customer#xyz.admin' there is a dashed line, whereas all other lines are solid lines.
|
||||||
|
Solid lines means, that one role is granted to another and followed in all queries to the restricted views.
|
||||||
|
The dashed line means that one role is granted to another but not automatically followed in queries to the restricted views.
|
||||||
|
|
||||||
|
The reason here is that otherwise simply too many objects would be accessible to those with the 'administrators' role and all queries would be slowed down vastly.
|
||||||
|
|
||||||
|
Grants which are not followed are still valid grants for `hsadminng.assumedRoles`.
|
||||||
|
Thus, if you want to access anything below a customer, assume its role first.
|
||||||
|
|
||||||
|
There is actually another speciality in the customer roles:
|
||||||
|
For all others, a user defined by the customer gets the owner role assigned, just for the customer, the owners role is assigned to the 'administrators'.
|
||||||
|
|
||||||
|
|
||||||
|
### Package Roles
|
||||||
|
|
||||||
|
One example of the business-object-type-level right below is the *Package*.
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
' left to right direction
|
||||||
|
top to bottom direction
|
||||||
|
|
||||||
|
' hide the ugly E in a circle left to the entity name
|
||||||
|
hide circle
|
||||||
|
|
||||||
|
' use right-angled line routing
|
||||||
|
' skinparam linetype ortho
|
||||||
|
|
||||||
|
entity "BObj pacage#xyz00" as boPacXyz00
|
||||||
|
|
||||||
|
together {
|
||||||
|
entity "Perm pacage#xyz00 *" as permPackageXyzAll
|
||||||
|
permPackageXyzAll --> boPacXyz00
|
||||||
|
|
||||||
|
entity "Perm pacage#xyz00 add-unixuser" as permPacXyz00AddUser
|
||||||
|
permPacXyz00AddUser --> boPacXyz00
|
||||||
|
|
||||||
|
entity "Perm pacage#xyz00 edit" as permPacXyz00Edit
|
||||||
|
permPacXyz00Edit --> boPacXyz00
|
||||||
|
|
||||||
|
entity "Perm pacage#xyz00 view" as permPacXyz00View
|
||||||
|
permPacXyz00View --> boPacXyz00
|
||||||
|
}
|
||||||
|
|
||||||
|
package {
|
||||||
|
entity "Role customer#xyz.tenant" as roleCustXyzTenant
|
||||||
|
entity "Role customer#xyz.admin" as roleCustXyzAdmin
|
||||||
|
entity "Role customer#xyz.owner" as roleCustXyzOwner
|
||||||
|
}
|
||||||
|
|
||||||
|
package {
|
||||||
|
entity "Role pacage#xyz00.owner" as rolePacXyz00Owner
|
||||||
|
entity "Role pacage#xyz00.admin" as rolePacXyz00Admin
|
||||||
|
entity "Role pacage#xyz00.tenant" as rolePacXyz00Tenant
|
||||||
|
}
|
||||||
|
|
||||||
|
rolePacXyz00Tenant --> permPacXyz00View
|
||||||
|
rolePacXyz00Tenant --> roleCustXyzTenant
|
||||||
|
|
||||||
|
rolePacXyz00Owner --> rolePacXyz00Admin
|
||||||
|
rolePacXyz00Owner --> permPackageXyzAll
|
||||||
|
|
||||||
|
roleCustXyzAdmin --> rolePacXyz00Owner
|
||||||
|
roleCustXyzAdmin --> roleCustXyzTenant
|
||||||
|
|
||||||
|
roleCustXyzOwner ..> roleCustXyzAdmin
|
||||||
|
|
||||||
|
rolePacXyz00Admin --> rolePacXyz00Tenant
|
||||||
|
rolePacXyz00Admin --> permPacXyz00AddUser
|
||||||
|
rolePacXyz00Admin --> permPacXyz00Edit
|
||||||
|
|
||||||
|
entity "Role administrators" as roleAdmins
|
||||||
|
roleAdmins --> roleCustXyzOwner
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
Initially, the customer's admin role gets the package owner role granted.
|
||||||
|
They can use the package's admin role to hand over most management functionality to a third party.
|
||||||
|
The 'administrators' can get access through an assumed customer's admin role or directly by assuming the package's owner or admin role.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user