Originally posted by lvca September 17, 2021
SUMMARY
Status: Design
Progress: Design 100% -> Development & Unit Tests 0% -> Integration Tests 0%
Currently Assigned: @lvca
ETA: 5 days
From: Ideas [#44]
To: Issues []
ArcadeDB supports super-simple security for users in a server. Example of security.json
file:
{
"users": {
"root": {
"databases": [],
"password": "PBKDF2WithHmacSHA256$65536$esd1hjs=...",
"name": "root",
"databaseBlackList": true
},
"elon": {
"databases": ["Universe"],
"password": "PBKDF2WithHmacSHA256$65536$lYhGpkO4Tgu53hBc3D...=",
"name": "elon",
"databaseBlackList": false
}
}
}
Below you can find the proposal to improve the Server Side security. This is going to be the new server-groups.json
file:
{
"databases": {
"*": {
"groups": {
"admin": {
"access": [
"updateSchema"
],
"types": {
"*": {
"access": [
"create",
"read",
"update",
"delete"
]
}
}
},
"*": {
"access": "",
"types": {
"*": {
"access": ""
}
}
}
}
}
},
"version": 1
}
Where all the user/password pairs are moved under the new file server-users.jsonl
in JSONL format (one JSON per line). This allows protecting the file with passwords from the actual security configuration. Also, the security.json file is designed to be a JSON file easily modifiable, while the server-users.jsonl file is managed by the ArcadeDB server and the passwords are not meant to be edited manually. Example of server-users.jsonl
:
{"user":"root","password": "PBKDF2WithHmacSHA256$65536$BHV+MGHvpXH89e0a6ZedqABDCnyeC8kSdBx+ik6APOs=$W8H+AXFC+YJHdM9X+PPoL59VBY1kY6uMUDTIQ515GwU="}
That means the admin group has access to every database installed in the server, and full CRUD operations on all the types.
Support for group
In order to provide a greater level of security, we need to introduce fine-level permissions. Instead of creating such profiling for each user, it's more flexible configuring groups and assign users to one or more groups. Example.
Given the "elon" users in server-users.jsonl
:
{"elon": {"groups": ["pragmatist", "genius"]}}
You can define the rules for each groups in a database
{
"databases": {
"Heroes": {
"groups": {
"pragmatist" : {
...
}
}
}
},
}
Type access rules are strings where each character means a type of permission (case sensitive).
For types the typical CRUD access:
- 'create' allows creating new records for the type
- 'read' allows reading records for the type
- 'update' allows updating records for the type
- 'delete' allows deleting records for the type
For the databases:
- 'updateSchema' allows modifying the schema
For the users:
- 'updateSecurity' allows modifying the security
In case a user belongs to multiple groups, the permissions are simply added to each other and the resulting is the sum of all the permissions.
The wildcard *
will be used to assign the defaults. In the default configuration above, the "admin" user applies to all groups, databases and types. Creating a database or a group with the name *
is forbidden.
Profile access to types for CRUD operations and more
Example of profiling at type level:
"Reviewers": {
"databases": {
"*": {
"types": {
"Post": {
"access": "r",
"limit": 10
},
"Comment": {
"access": "r",
"resultSetLimit": 100,
"readTimeout": 5000
},
"Note": {
"access": "crud"
}
}
}
},
}
The example above does not specify a database, but it's rather using the wildcard "*". This is a typical setting for multi-tenant, where a server hosts multiple databases, one per tenant, with the same structure.
The property resultSetLimit
, if present, tells to cut off resultsets larger than the value in this field. This is useful to avoid some users can stress the database by returning huge resultsets.
The property readTimeout
, if present, limits the query execution to the timeout expresses in milliseconds.
Add version for further compatibility
Adding a version allows the server to support the evolution of the security.json file. Example:
{
"users": {},
"groups": {},
"version": 1
}
API
if ArcadeDB runs as embedded without a server, the default implementation returns UnsupportedOperationException. When the server is running, it installs the server security. Users can implement their own security and register the component at startup. No SQL will be provided at first, if there is demand, we could implement server commands.
File auto-reload and format
The ServerSecurity
module should watch changes to the file and reload it automatically (with a message in console). At every reload of the file, the consistency must be checked before replacing the current configuration in RAM. In case of error, the current configuration must be serialized in JSON into the file "config/security-prev.json". If the configuration in RAM is empty, then the previous file "config/security-prev.json" (if any) must be loaded and used.
The Security JSON file will be written with an indent = 2 to make easier editing offline with an editor.
FAQ
Wouldn't be better to have a separate database to save users, groups, etc?
There are pros and cons, but the flexibility to edit a JSON file to modify the security is the first reason, then all the security is loaded in RAM, so there would be no access to the database.
What if I have hundreds or thousands of users?
The JSON file can be large. All the users are loaded in RAM, so check the amount of RAM you're reserving for the ArcadeDB Server process.