Protect your functions on open instances using capabilities. They can restrict the access of several sensitive functions to specific users.
Warp 10 instances can be accessed by many users and may even be open to anyone. To protect your instances from abuse or simply bad use, limits are put in place to avoid WarpScript running amok. Although this can be used for access control, this is a very crude way of doing this.
If, for instance, you add an extension to your instance to interact with a SQL database. You may want to control which user can access the SQLEXEC
function. On a production instance, you may want to add debug and logging extensions to identify a problem while limiting those functions to the dev or ops team.
Starting with the 2.8.0 version, you can now use capabilities in tokens to finely control accesses.
The Capabilities Mechanism
Capabilities are special token attributes. They can be added to or removed from the execution environment. Those capabilities can then be checked by macros and functions to allow, deny or restrict their usage.
To set a token capability, add .cap:name_of_capability
as a key to the attribute of the token. The capability must have a value, which can be of use or not. Here is an example of how to add the my_capability
with foo
value:
'da7aba5e-ea75-b055-cafe-fee15ca1ab1e' 'owner' STORE
{
'type' 'READ'
'owner' $owner
'application' 'noapp'
'expiry' '2121-06-01T00:00Z' TOTIMESTAMP 1 ms /
'owners' [ $owner ]
'producers' [ $owner ]
'applications' [ 'noapp' ]
'attributes' {
'.cap:my_capability' 'foo'
}
}
'my_token_secret' // token.secret configuration
TOKENGEN
The above script requires you to enable the TokenGen extension by adding
warpscript.extension.token = io.warp10.script.ext.token.TokenWarpScriptExtension
To one of your configuration files. Then, you need to restart your instance for the configuration to take effect.
The resulting token can now be used to add the my_capability
capability to the execution environment. To do so, simply use CAPADD
on the token. CAPADD
does not overwrite already existing capabilities so, if you need to combine tokens with overlapping capabilities, make sure to use CAPDEL
to remove preexisting capabilities you want to overwrite.
If you add "my_capability" CAPCHECK
after CAPADD
, you can check if the capability is present or not. This will be very useful for macros to check for required capabilities, as you will see below. You can also get the capability value with CAPGET
, for instance, to get a limit.
You can add several capabilities per token. Also, if you want pure-capabilities tokens, you can add the .noauth
and .nofind
attributes, with any value, to make the token unusable with AUTHENTICATE
, FIND
and FETCH
.
Capabilities and Shadowing
One of the most useful uses of capabilities is to protect functions. In the following example, we will protect the REV
function. This is of little use, except for demonstration purposes.
To be able to change the behavior of the REV
function we first need to enable the Shadow extension and configure it. In configuration file, add:
warpscript.extension.shadow = io.warp10.script.ext.shadow.ShadowWarpScriptExtension
shadow.macroprefix = shadow
shadow.rename.REV = 07ed7492-3dcd-4d07-8b21-6b4cf6e8fc34.REV
shadow.macro = REV
Next, restart your instance after this change. In the configuration above, the first line enables the extension which will allow us to override functions with macros. The second line tells shadow that when overriding a function FOO
, it will be done using the @shadow/FOO
macro. The third line renames the original REV
function to some impossible-to-guess name. The last line overrides REV
with @shadow/REV
.
Now that the configuration is done we have to define this macro which will use capabilities to determine whether to display the revision number or not. Add a REV.mc2 file in ${WARP10_HOME}/macros/shadow/
with the following content:
<%
'my_capability' CAPCHECK
<% 07ed7492-3dcd-4d07-8b21-6b4cf6e8fc34.REV %>
<% 'Not allowed to check revision' %>
IFTE
%>
Now whenever you execute REV
, it will return "Not allowed to check revision"
if you didn't add the capability or the revision if you did. This effectively restricts the access to REV
to those who have a token with the my_capability
capability.
Capabilities and Extensions
You can also use capabilities directly into your extension. It can be used to limit access to a function or a group of function. It can also be used to restrict the parameters which can be given to a function. If you need to build an extension which make use of capabilities, the related functions are in the Capabilities
class. The most useful method in this class is the get(stack, capability_name)
to get the capability value of the execution environment.
As an example, the HTTP function, introduced in the 2.8.0 version, makes heavy use of capabilities. It can check whether the user is allowed to do an HTTP call and how many, as well as the allowed download size. You can check in the code how it is done if you want to replicate this behavior.
This shows that either the presence of a capability or its value can be useful to control or limit the use of sensitive functions.
Takeaways
Capabilities is a mechanism introduced in the 2.8.0 version of Warp 10. It allows very fine control of how functions can be used: you can restrict functions to certain users based on provided tokens.
As this mechanism is based on tokens, this is fairly transparent to the user who can use its tokens both to fetch, update and delete data as well as to access restricted functions.
Read more
Using Warp 10 as a map tile server for Discovery
Create a custom tile for Discovery
Thinking in WarpScript - Finding your Time Series
WarpScript™ Doctor