Automatically translate this page?
20 December, 2017

Take control of token access permissions with flexible ACLs

Manage the scope of elements and modules that a user can access within the flespi platform.

Disclaimer: we have changed the token creation form: "flags" and "acl" properties turned into the "access" object with "type" (in place of "flags") and "acl" properties.

Not everyone needs access to all data and all objects within the flespi platform, right? Access control is a handy mechanism to give different permissions to different types of platform users.

Not so long ago we added access restrictions for API tokens using access control lists (ACLs). Now it’s easy to customize permissions for various tokens (see Tokens menu item on flespi.io) depending on the requirements: e.g. token working with specific channels/devices/streams only, token with read-only access to collect statistics from the platform components, etc.

ACL basics

What’s not allowed is forbidden. ACL mechanism only grants access — by default all actions are denied for the token with enabled ACL and any action not specified in ACL is forbidden.

Defined ACL does not mean enabled ACL. Use the flags field in the token dialog to enable the mechanism.

Access to the platform module is granted only via token flags ("Master" flag). There is no way to allow tokens to create other tokens via ACL. ACL mechanism is not designed for flespi administration.

flespi token acl flag

Using this switch you can easily disable ACL for a token but preserve its value.

Token ACL consists of access control entries (ACEs). ACE contains all the necessary data to allow the specific action for the token. Since all the ACL stuff applies to flespi platform REST API, the ACE structure contains module names or object types, HTTP requests names, and optional object identifiers. Let's take a closer look at the ACE fields:

  • Module name or object type (uri field in API). The first value you should select when creating a new ACE in ACL. It defines what specific platform module or object type the ACE applies to:
    flespi token acl modules objects uri
  • Allowed HTTP requests (methods field in API). Determines which of the four HTTP request methods (GET, POST, PUT, DELETE) can apply to the specified module or objects (see previous step).
    flespi token acl request methods
  • Objects identifiers (ids field in API) [optional]. Grant access to a specific set of objects. Obvious note: Only identifiers belonging to the current customer account are allowed.

    Possible values:
    • specific ids — grant access to the objects with listed ids;
      flespi token acl numeric values
    • all keyword — allows the token to access all existing objects of the specified type and all objects of this type created in the future (for the current customer);
      flespi token acl all
    • empty string — enables the user to not only access but also manage (create) objects of the given type.

Notes

Requests with keyword all in place of identifiers list in the URI work fine in ACL. In such case, a token only works with the objects it has enough permissions for.

During the validation process, only one ACE is selected to verify the access for the token. This one ACE is the most suitable for the current request by the following criteria:

  • it matches the request URI better than other ACEs (e.g. for request by URI /gw/channels/all/messages ACE with uri field gw/channels matches better than ACE with urifield gw; for the same request ACE with uri field gw/channels and with specified identifiers matches better than ACE with uri field gw/channels and without identifiers)
  • it matches the request HTTP method.

These criteria apply to the ACEs in ACL sequentially. The first and the only one matching ACE is selected to continue the validation process. If the matching ACE does not contain identifiers value, the current request processing continues as is. Otherwise, access only for the specified identifiers is allowed. If there are more ACEs matching the selection criteria, they are not taken into account. If no matching ACE is found, access to the current request is denied at all.

From the previous paragraph it follows that ACL can contain any number of ACEs with the same specified platform module or objects and their identifiers. It allows to reduce the size and to improve the readability of an ACE. But the current implementation requires putting specifications for the same objects or modules and the same request type into one ACE.
Short example. Say there is an ACL with two ACEs: the first allows PUT requests for gw/devices objects with identifiers 1 and 2, the second allows PUT requests for gw/devices objects with identifiers 1, 2, and 3. The attempt to modify the device 3 via PUT request would be declined because the first most suitable ACE allows using PUT with devices 1 and 2 only.

Examples

So, for now, I have four tokens in my account:

  • master token (used to login to the flespi panel and to access to the flespi platform API)
  • token with granted access (read via GET, and update via PUT) to the two of my channels
  • token with granted read-only access to the whole storage module
  • token with full permissions to storage/containers
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nafbfWtmEYCjHva4PqsloIQeLgWOSAc3yf2E2jOw7gEEBEwhVPs9n7bWdYATmBKK' \
'https://flespi.io/platform/customer/tokens/all?fields=key,acl'
{
"result": [
{
"acl": [],
"key": "nafbfWtmEYCjHva4PqsloIQeLgWOSAc3yf2E2jOw7gEEBEwhVPs9n7bWdYATmBKK"
},
{
"acl": [
{
"ids": [
2025,
2026
],
"methods": [
"GET",
"PUT"
],
"uri": "gw/channels"
}
],
"key": "UGw2y0OswbAdg4OjjfLplZ0pfqfr9KNRf8JBWlTimjlqcYzj18yaXnp1DviB3Tg6"
},
{
"acl": [
{
"methods": [
"GET"
],
"uri": "storage"
}
],
"key": "nFkUSDbhXAiCgGfrn35rMfANB2wIls5xVdhDEgJsEPUKl01wRXNu0d5r5p0fFTCo"
},
{
"acl": [
{
"methods": [
"GET",
"POST",
"PUT",
"DELETE"
],
"uri": "storage/containers"
}
],
"key": "G13pmI0T2CuPAOPydVvvmqXVi3nD1pWveQKooz7fZsSp6xL7g6qqkcct5nWVAIgE"
}
]
}

Let's work with three tokens with enabled ACL and compare the results against the master token.

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nafbfWtmEYCjHva4PqsloIQeLgWOSAc3yf2E2jOw7gEEBEwhVPs9n7bWdYATmBKK' \
'https://flespi.io/gw/channels/all?fields=id'
{"result":[{"id":2024},{"id":2025},{"id":2026}]}
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken UGw2y0OswbAdg4OjjfLplZ0pfqfr9KNRf8JBWlTimjlqcYzj18yaXnp1DviB3Tg6' \
'https://flespi.io/gw/channels/all?fields=id'
{"result":[{"id":2025},{"id":2026}]}

As you can see, the second token requested all tokens but received only those allowed for access by this token. What about the third channel?

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken UGw2y0OswbAdg4OjjfLplZ0pfqfr9KNRf8JBWlTimjlqcYzj18yaXnp1DviB3Tg6' \
'https://flespi.io/gw/channels/2024?fields=id'
{"errors":[{"code":6,"id":2024,"reason":"access denied to '\/channels\/2024'"}],"result":[]}

No access — as we expected. Now let's try to disable the channels.

curl -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{"enabled": false}'\
-H 'Authorization: FlespiToken UGw2y0OswbAdg4OjjfLplZ0pfqfr9KNRf8JBWlTimjlqcYzj18yaXnp1DviB3Tg6' \
'https://flespi.io/gw/channels/all?fields=id,enabled'
{"result":[{"enabled":false,"id":2025},{"enabled":false,"id":2026}]}
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nafbfWtmEYCjHva4PqsloIQeLgWOSAc3yf2E2jOw7gEEBEwhVPs9n7bWdYATmBKK' \
'https://flespi.io/gw/channels/all?fields=id,enabled'
{"result":[{"enabled":true,"id":2024},{"enabled":false,"id":2025},{"enabled":false,"id":2026}]}

Even though I've tried to disable all the channels ACL allowed me to disable only two out of three.

And the final action. Let's clean the channel messages and see what we get.

curl -X DELETE -H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{"delete_key": 1513762868}' \
-H 'Authorization: FlespiToken UGw2y0OswbAdg4OjjfLplZ0pfqfr9KNRf8JBWlTimjlqcYzj18yaXnp1DviB3Tg6' \
'https://flespi.io/gw/channels/all/messages'
{"errors":[{"code":8,"reason":"action is not permitted by ACL"}],"result":[]}

Yes, ACL is still here guarding flespi customers against dishonest token usage.

OK, enough with channels. There are two more tokens with different permissions to the storage module. What do we have in this module?

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nFkUSDbhXAiCgGfrn35rMfANB2wIls5xVdhDEgJsEPUKl01wRXNu0d5r5p0fFTCo' \
'https://flespi.io/gw/channels/all?fields=id'
{"errors":[{"code":8,"reason":"action is not permitted by ACL"}],"result":[]}

Oops. Yes, this token is for the storage module only so focus on it.

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nFkUSDbhXAiCgGfrn35rMfANB2wIls5xVdhDEgJsEPUKl01wRXNu0d5r5p0fFTCo' \
'https://flespi.io/storage/containers/all?fields=id'
{"result":[{"id":5126},{"id":5127},{"id":5128}]}
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nFkUSDbhXAiCgGfrn35rMfANB2wIls5xVdhDEgJsEPUKl01wRXNu0d5r5p0fFTCo' \
'https://flespi.io/storage/abques/all?fields=id'
{"result":[{"id":7756},{"id":7757},{"id":7758}]}

What about the last token?

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken G13pmI0T2CuPAOPydVvvmqXVi3nD1pWveQKooz7fZsSp6xL7g6qqkcct5nWVAIgE' \
'https://flespi.io/storage/containers/all?fields=id'
{"result":[{"id":5126},{"id":5127},{"id":5128}]}
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken G13pmI0T2CuPAOPydVvvmqXVi3nD1pWveQKooz7fZsSp6xL7g6qqkcct5nWVAIgE' \
'https://flespi.io/storage/abques/all?fields=id'
{"errors":[{"code":8,"reason":"action is not permitted by ACL"}],"result":[]}

No surprise the token is for containers only. And this token has full permissions not only for containers objects but also for the entire containers submodule.

curl -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' \
-d '[{"name": "container 42"}]' \
-H 'Authorization: FlespiToken G13pmI0T2CuPAOPydVvvmqXVi3nD1pWveQKooz7fZsSp6xL7g6qqkcct5nWVAIgE' \
'https://flespi.io/storage/containers'
{"result":[{"flags":0,"id":5129,"name":"container 42"}]}

Success! And both storage-related tokens can see this new container too.

curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken G13pmI0T2CuPAOPydVvvmqXVi3nD1pWveQKooz7fZsSp6xL7g6qqkcct5nWVAIgE' \
'https://flespi.io/storage/containers/5129'
{"result":[{"flags":0,"id":5129,"name":"container 42"}]}
curl -X GET -H 'Accept: application/json' \
-H 'Authorization: FlespiToken nFkUSDbhXAiCgGfrn35rMfANB2wIls5xVdhDEgJsEPUKl01wRXNu0d5r5p0fFTCo' \
'https://flespi.io/storage/containers/5129'
{"result":[{"flags":0,"id":5129,"name":"container 42"}]}

As you can see from the numerous examples above, the access control mechanism empowers customers of the flespi platform to manage permissions to the elements of the infrastructure depending on the needs and duties of specific users. Tighten the bolts where needed and give full control where allowed.



Get the latest updates and monthly newsletters from flespi in your inbox

6 September, 2018 | flespi features | Anton Kulichenko

Migration between GPS tracking systems with zero data loss… and more

Proxy protocol allows forking the raw telematics data from trackers to up to three platforms, store messages, and easily debug connection issues.

Wialon & flespi — Seven Common Use Cases to Join Forces

Many standard situations that Wialon users face can be resolved easier by plugging flespi in the infrastructure. Here are a few best practices where flespi adds value and eliminates hassle.