Securing file storage
The security rules for file storage access works to authorize client request. Authorization works on the operation level (read, create and delete) for each path prefix. This means that you can have different rules for different path prefixes. Here's a sample snippet which shows the rules on the
/images/:userId prefix. Operations
read are allowed while
delete is blocked.
modules: fileStore: enabled: true storeType: local conn: /tmp/data rules: # `rules` is a map of mutiple rules imageRule: prefix: /images/:userId # `prefix` is the path prefix on which the rule applies rule: create: # `create` is the rule object for file write operations rule: allow read: # `read` is the rule object for file real operations rule: allow delete: # `delete` is the rule object for file delete operations rule: deny # Config for other modules go here
Points to note
The following needs to be kept in mind for the security rules in the file storage module.
rulesis a map of rules. The key (
imageRulein this case) is just a unique key to indentify each rule.
- All rules are applied on a
prefixis nothing but the path prefix where the file / folder is present or is to be created
- The prefix may contain path parameters (
/:userIdin this case). The value of the path parameter is available in the
args.paramsobject. The key would be
userIdand the value would be the actual value in the path provided.
With security rules for functions you can:
- Allow / deny access to a file/folder.
- Allow access to a particular file/folder only if the user is authenticated.
- Allow access to a particular file/folder only if certain conditions are met (via JSON rules or custom logic).
Popular use cases
- Allow only signed in users to upload a file.
- Role based authentication (For example only allow admin to delete a particular folder)
- Allow user to upload a file at his path only.
- The Instagram problem - Allow user to view a profile pic only if the profile is public or they are following them
- Call another function to authorize the file/folder access
All these problems can be solved by the security module of Space Cloud.
All requests for file/folder access contains 2 variables which are availabe to you for matching conditions:
- auth: The claims present in the JWT token. If you are using in-built user management service of Space Cloud, then the
roleof the user. While making a custom service, you are free to choose the claims which go inside the JWT token and thus available in the
- params: The variables in the path prefix.
Allow anonymous access
You can disable authentication and authorization for a particular file/folder completely by using
allow. The request is allowed to be made even if the JWT token is absent in the request. You might want to use this when you want some files to be publicly available to all users even without signin (For example, access images of products in an e-commerce app). Here's how to give access to a particular path using
rule: read: rule: allow
This rule is to deny all incoming requests irrespective of any thing. It is especially useful to deny certain dangerous operations like
delete while selectively allowing the other ones. (For example, deny access to delete product's image). Here's how to deny access to a particular operation using
rules: delete: rule: deny
Allow only authenticated users
You can allow access to a certain path only if the user is authenticated. This rule is used to allow the request only if a valid JWT token is found in the request. No checks are imposed beyond that. Basically it authorizes every request which has passed the authentication stage. Here's how to allow a operation for authenticated users:
rules: create: rule: authenticated
Allow operation on certain conditions
Many a times you might want a user to access a file path only when certain conditions are met. For example, a user can delete a picture only if it is uploaded by him. Another use case might be allowing a user to read a profile's image only if that profile is public or the user is following him (Instagram problem). Such conditions might require you to check the value of certain fields from the incoming request or from the database. Or it can be a custom validation altogether. The security rules in Space Cloud are made keeping this flexibility in mind.
Match incoming requests
This rule is used to allow a certain request only when a certain condition has been met and all the variables required for matching is present in the request itself. Each file access request contains 2 variables (
params) present in the
args object. Generally this rule is used to match the path parameters with the auth object. It can also be used for role based authentication.
The basic syntax looks like this:
rule: match eval: == | != | > | >= | < | <= # Any one of them type: string | number | bool # Any one of them f1: field1 # A value or variable f2: field2 # A value or variable
Example (Make sure user can upload a file at his path only):
rules: profilePicRule: prefix: /users/:userId # `prefix` is the path prefix on which the rule applies rule: create: # `create` is the rule object for file write operations rule: match eval: == type: string f1: args.params.userId # params contain the userId variable from the path prefix f2: args.auth.id # Assuming role is the JWT claim containing the role of user
Example (Role based authentication - allow only admin to delete a folder):
rules: profilePicRule: prefix: /projects/:projectId # `prefix` is the path prefix on which the rule applies rule: delete: # `create` is the rule object for file write operations rule: match eval: == type: string f1: args.auth.role # Assuming role is the JWT claim containing the role of user f2: admin
This rule is used to allow a certain request only if a database request returns successfully. The query's find clause is generated dynamically using this rule. The query is considered to be successful if even a single row is successfully returned.
The basic syntax looks like this:
rule: read db: mongo | sql-mysql | sql-postgres # Any one of them col: collection # Name of the table / collection find: mongo-find query # Find object following MongoDB query syntax
query rule executes a database query with the user defined find object with operation type set to
one. It is useful for policies which depend on the values stored in the database.
Example (make sure user can query images of only public
rules: profilePicRule: prefix: /profiles/:profileId read: rule: read db: mongo col: profiles find: userId: args.params.profileId # Assuming profiles has field `userId` isPublic: true # Assuming profiles has field `isPublic`
Combine multiple conditions
You can mix and match several
query rules together to tackle complex authorization tasks (like the Instagram problem) using the
The basic syntax looks like this:
rule: and | or clauses: array_of_rules
Example (The Instagram problem - Make sure the user can view a profile picture if the profile is public or he is a follower)
rules: profilePicRule: prefix: /profiles/:profileId read: rule: or clauses: - rule: read db: mongo col: profiles find: userId: args.params.profileId # Assuming profiles has field `userId` isPublic: true - rule: read db: mongo col: profiles find: followers: $in: args.auth.userId # Assuming followers is an array of user ids
In case where the matching and db query for validating conditions are not enough, you can bring your own custom validation logic by writing a function with the functions module. You can configure Space Cloud to use your function to authorize a particular request. Here's an example showing how to do this by rule
## Asuming you have written a service `my-service` with a function `my-service` using functions mesh rules: profilePicRule: prefix: /profiles/:profileId read: rule: func service: my-service func: my-func
In the above case,
my-func will receive the path
params objects as the arguments of the function. See functions mesh to understand how to write a function. The request will be considered authorized by the Space Cloud in this case only when the function returns an object with
ack property set to true.
Great! You have learned how to secure file access. You may now checkout the security rules for functions module.