Security & Access Control
Fractl allows role-based-access-control for an application to be expressed in a very declarative way. For instance,
if only managers are allowed to create new companies and employees are only allowed to view company-data,
an appropriate :rbac
spec could be added to the :Company
entity definition:
(entity :Acme.Core/Company
{:Name {:type :String :guid true}
:rbac [{:roles ["manager"] :allow [:create]}
{:roles ["employee"] :allow [:read]}]})
When a user belonging to the "manager" role creates an instance of :Company
, that user also becomes the owner of that
instance. A user may read, update or delete an entity-instance that it owns. The user may also assign new owners
or grant permissions on that instance to other users.
Note The role named admin
is special - users belonging to the admin
role can execute CRUD operations on all entities in the system. (In other words, they become superusers of the system).
Identity management
Users are represented by instances of the :Fractl.Kernel.Identity/User
entity. New users are usually added to the application
through the /signup
API:
$ curl -X POST http://localhost:8080/signup/ \
-H 'Content-Type: application/json' \
-d '{
"Fractl.Kernel.Identity/SignUp": {
"User": {
"Fractl.Kernel.Identity/User": {
"Name": "joe",
"Password": "Ch7Sjj@123",
"Email": "joe@acme.com",
"FirstName": "Joe",
"LastName": "Jay"
}
}
}
}'
Once a user has signed-up, he/she may login to the application as,
$ curl -X POST http://localhost:8080/login/ \
-H 'Content-Type: application/json' \
-d '{"Fractl.Kernel.Identity/UserLogin":
{"Username": "joe@acme.com", "Password": "Ch7Sjj@123"}}'
If the login succeeds, an auth-token is returned - which has to be added to each subsequent RESTful API call.
$ curl -X POST http://localhost:8080/api/Acme.Core/Company \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJr...' \
-d '{"Acme.Core/Company { .... }}'
Assigning roles
When a user signs-up he/she may be assigned a default role, the most convenient way to do this is by implementing a dataflow for the
:Fractl.Kernel.Identity/PostSignUp
event. The following example shows how a newly signed-up user is added to the "employee" role
by default:
(dataflow :Fractl.Kernel.Identity/PostSignUp
;; Query the user by email.
{:Fractl.Kernel.Identity/User
{:Email? :Fractl.Kernel.Identity/PostSignUp.SignupRequest.User.Email}
:as [:U]}
;; Add the user to the employee-role.
{:Fractl.Kernel.Rbac/RoleAssignment
{:Role "employee" :Assignee :U.Email}}
;; Return the user to complete the sign-up-process.
:U)
A superuser may evaluate a custom dataflow to add a user to the "manager" role. Superusers and configuration related to rbac is discussed in the section on rbac-settings.
RBAC on relationships
For :contains
relationships, the default rbac rule is this - the user must be the owner of the parent-node to create the
relationship. For :between
relationships, the default rule is that the user must be the owner of both nodes. It's possible
to override these rules by explicitly setting an :rbac
spec for relationships.
For :between
relationships some additional options are available. This is illustrated below:
(relationship :Social/Friendship
{:meta {:between [:Social/Person :Social/Person :as [:From :To]]}
:rbac {:owner :From
:assign {:ownership [:To :-> :From]}}})
The :owner
setting means - the owner of the :From
node can create the relationship - she need not be the owner
of :To
. The :assign
setting controls dynamic-assignment of ownership. Here, when an instance of the relationship
is created the owner of :To
is added to the owners list of :From
. This allows the owner of :To
to perform additional
operations of :From
, that was not possible when the relationship did not exist. This ownership assignment will be revoked when
the relationship instance is deleted from the system.
RBAC settings
RBAC is enabled by the following simple setting in config.edn
:
{:rbac-enbled true}
A few environment variables need to be set so that the Fractl runtime can interact with the identity-backend, which defaults to Amazon Cognito. These environment variables are:
* FRACTL_SUPERUSER_EMAIL - the email address of the superuser
* FRACTL_SUPERUSER_PASSWORD - the password of the superuser
* AWS_REGION - the aws region where cognito is configured, e.g us-west-2
* AWS_ACCESS_KEY - an access key obtained from AWS
* AWS_SECRET_KEY - a secret key obtained from AWS
* AWS_COGNITO_CLIENT_ID - client id for accessing the cognito pool
* AWS_COGNITO_USER_POOL_ID - cognito pool id
The superuser maybe manually configured in Cognito and setup with an appropriate password there.