Best way to get data from restricted database with XPages - xpages

I'm working on two Domino databases that contain XPages :
the 1st database is a public database,
the 2nd one is restricted to a group (let's say the HR team)
I'm building an XPage in the public DB and I need to populate a sessionScope variable with the data of the HR's database (for example the HR id of the user)
So, as the normal users will not have access to the HR DB, a #Dblookup is not allowed.
Using sessionAsSigner method needs to re-sign all elements of the db each time a developer is modifying a XPages component (otherwise the sessionAsSigner element is unknown).
Then, how to query a database that I do normally not have access ?
Do I have to call an agent with higher access than the connected users ?
And then, how to populate the sessionScope variable ?
Any help will be greatly appreciated

There are a few options, but as Knut says, without a shadow of a doubt, the best practice approach is to use sessionAsSigner.
Source control can be used to allow multiple developers to work on their own instance of the design. Swiper can be used to suppress signatures from the source control repository to minimise conflicts.
All other options I can think of (e.g. periodic exports, using a runOnServer agent) will take longer to code, be more complex and will require you, as the developer, to manage the security implications of exposing the data.

Related

Access Control in a Web Application

I'm currently reading a lot about access control possibilites/mechanisms that can be used to protect resources in an application or web application. There's ACL, RBAC, ABAC and many other concepts out there.
Assuming I have developed a simple webservice that returns knowledgebase articles on a route like '/api/article'. The 'controller' connects to the database and fetches all articles and returns them as XML or JSON.
Now I would like to have control over which article in the database is accessible for which user or group. So for instance if user 'peter' accesses the route '/api/article' with his credentials, the webservice shall return only articles that are visible for 'peter'.
I would want to use ACL to control what each user/group can read/write/delete. But what I don't quite understand:
Where does one enforce the access control? Do I just fetch all records in the controller if a user accesses the route '/api/articles' and check each single record against an access control list (that doesn't sound very good performance wise)? Or is there a way that the 'SELECT' statement to the database only return the records that can actually be seen by that specific user?
I really tried hard to find more information on that topic, and there is a lot about different access control mechanisms, but not about where and how the actual enforcement happens...and it even get's more complex if it comes to other actions like modification, deletion and so on...
This is really a matter of implementation and everyone does it its own way. It also depends on the nature of the data, particularly on the size of your authorization (do your have 5 roles and users are attached to them or does each user have a specific set of articles he can access, different for each user - for instance)
If you do not want to make the processing on the controller, you could store the authorization information in your database, in a table which links a user to a set of KB articles, or a role (which would then be reflected in the article). In that case your SELECT query would just pass the authenticated user ID. This requires that the maintenance of the relationship is done of the database, which may not be obvious.
Alternatively you can store the ACL on the controller and build a query from there - for specific articles or groups of articles.
Getting all the articles and checking them on the controller is not a good idea (as you mention), DBs have been designed also to avoid such issues.

BuildFire: difference between userData and datastore?

I see that userData and datastore are 2 somewhat similar frameworks provided by BuildFire to help developers build robust mobile apps. In their respective documentation (listed below), they have similar wording. I get that they are both ways of storing data, but I would like to know what each framework's intended use is? What are the optimal use cases for each, and what is the criteria for choosing one over the other?
datastore: https://github.com/BuildFire/sdk/wiki/How-to-use-Datastore
userData: https://github.com/BuildFire/sdk/wiki/User-Data:-Save-user-data-from-the-widget
My "guess" would be that userData is for saving information that is user-specific, but can't this information also be stored in the datastore as well? I would love a clarification.
So there are 3 data storage services in BuildFire.
DataStore: Think of this as a CMS. Read and Write on the control panel and Read-Only on the widget/app side. It also has draft and live mode. Basically as you change the data in the control panel the app doesnt see any of it until you hit publush
UserData: This is read/write on both the control and the widget side. However, this is tied to a particular user. Meaning, all data is under the scope the currently logged in user
PublicData: Is similar to UserData -read/write everywhere- however, its scope is across all users. Meaning, all users can access and change data in public data.
It is worth mentioning that all these methods are automatically scoped to a plugin instance. Which means that data changed in one plugin instance will be completely independent of all other plugins
I hope this helps

Securing the data accessed by Neo4j queries

I wish to implement security on the data contained in a Neo4j database down to the level of individual nodes and/or relationships.
Most data will be available to all users but some data will be restricted by user role. I can add either properties or labels to the data that I wish to restrict.
I want to allow users to run custom cypher queries against the data but hide any data that the user isn't authorised to see.
If I have to do something from the outside then not only do I have to filter the results returned but I also have to parse and either restrict or modify all queries that are run against the data to prevent a user from writing a query which acted on data that they aren't allowed to view.
The ideal solution would be if there is a low-level hook that allows intercepting the reads of nodes and relationships BEFORE a cypher query acts on those records. The interceptor would perform the security checks and if they fail then it would behave as though the node or relationship didn't exist at all. i.e. the same cypher query would have different results depending on who ran it. And this would apply to all possible queries e.g. count(n) not just those that returned the nodes/relationships.
Can something like this be done? If it's not supported already, is there a suitable place in the code that I could add such a security filter or would it require many code changes?
Thanks, Damon
As Chris stated, it's certainly not trivial on database level, but if you're looking for a solution on application level, you might have a look at Structr, a framework on top of and tightly integrated with Neo4j.
It provides node-level security based on ACLs, with users, groups, and different access levels. The security in Structr is implemented on the lowest level possible, f.e. we only instantiate objects if the querying user has the approriate access rights.
All higher access levels like REST API and UI see only the records available in the user's context.
[1] http://structr.org, https://github.com/structr/structr

parse.com security

Recently I discovered how useful and easy parse.com is.
It really speeds up the development and gives you an off-the-shelf database to store all the data coming from your web/mobile app.
But how secure is it? From what I understand, you have to embed your app private key in the code, thus granting access to the data.
But what if someone is able to recover the key from your app? I tried it myself. It took me 5 minutes to find the private key from a standard APK, and there is also the possibility to build a web app with the private key hard-coded in your javascript source where pretty much anyone can see it.
The only way to secure the data I've found are ACLs (https://www.parse.com/docs/data), but this still means that anyone may be able to tamper with writable data.
Can anyone enlighten me, please?
As with any backend server, you have to guard against potentially malicious clients.
Parse has several levels of security to help you with that.
The first step is ACLs, as you said. You can also change permissions in the Data Browser to disable unauthorized clients from making new classes or adding rows or columns to existing classes.
If that level of security doesn't satisfy you, you can proxy your data access through Cloud Functions. This is like creating a virtual application server to provide a layer of access control between your clients and your backend data store.
I've taken the following approach in the case where I just needed to expose a small view of the user data to a web app.
a. Create a secondary object which contains a subset of the secure objects fields.
b. Using ACLs, make the secure object only accessible from an appropriate login
c. Make the secondary object public read
d. Write a trigger to keep the secondary object synchronised with updates to the primary.
I also use cloud functions most of the time but this technique is useful when you need some flexibility and may be simpler than cloud functions if the secondary object is a view over multiple secure objects.
What I did was the following.
Restrict read/write for public for all classes. The only way to access the class data would be through the cloud code.
Verify that the user is a logged in user using the parameter request.user ,and if the user session is null and if the object id is legit.
When the user is verified then I would allow the data to be retrieved using the master key.
Just keep a tight control on your Global Level Security options (client class creation, etc...), Class Level Security options (you can for instance, disable clients deleting _Installation entries. It's also common to disable user field creation for all classes.), and most important of all, look out for the ACLs.
Usually I use beforeSave triggers to make sure the ACLs are always correct. So, for instance, _User objects are where the recovery email is located. We don't want other users to be able to see each other's recovery emails, so all objects in the _User class must have read and write set to the user only (with public read false and public write false).
This way only the user itself can tamper with their own row. Other users won't even notice this row exists in your database.
One way to limit this further in some situations, is to use cloud functions. Let's say one user can send a message to another user. You may implement this as a new class Message, with the content of the message, and pointers to the user who sent the message and to the user who will receive the message.
Since the user who sent the message must be able to cancel it, and since the user who received the message must be able to receive it, both need to be able to read this row (so the ACL must have read permissions for both of them). However, we don't want either of them to tamper with the contents of the message.
So you have two alternatives: either you create a beforeSave trigger that checks if the modifications the users are trying to make to this row are valid before committing them, or you set the ACL of the message so that nobody has write permissions, and you create cloud functions that validates the user, and then modifies the message using the master key.
Point is, you have to make these considerations for every part of your application. As far as I know, there's no way around this.

User Access Checking for Rights on Particular Database Objects or Records

I'm having a friendly debate with a developer about a situation where users are logging in and accessing documents in a web application. When we load the document for the user to view, we have the userID in session and the documentID that may be passed via QueryString.
To prevent the user from modifying the documentID on the QueryString, I propose that the stored procedure that loads the document take the UserId as a parameter to validate rights to the document.
My developer friend suggests that we run a separate procedure to determine access rights to the document earlier in the page and just run a procedure to grab the document when the document should be shown.
Are we missing something? Which is most efficient and safe? I thought passing the UserId with the DocID into one procedure call to check rights and pull the document was a more efficient solution.
I propose that the stored procedure
that loads the document take the
UserId as a parameter to validate
rights to the document.
I think this is the way to go. If for no other reason than it's safer. If you reuse this proc, and then forget to check the access - you've opened a big hole. This way it's apparent and baked in that you can't get to the doc unless you have access.
Strictly from a performance perspective, passing the UserID along with the DocumentID into one stored procedure would be best. You only have one round trip to the database server. Also, as others have pointed out, if you will be retrieving this document from other pages or applications, if you use the same stored procedure, you insure that you are not bypassing the security to do so.
However there are scenarios where having dedicated security verification stored procedures makes sense. If you have other resources that you want to protect besides documents, and your verfication code isn't trivial, you may not want to duplicate the verfication code in every stored procedure in your database. In that case it may make sense to move the security infrastructure out to your data access layer, and have the data access layer make the db call to authorize access prior to retrieving the requested resource. If you take this route, you don't want to rely on the developer to always have to remember to make an authorization db call prior to requesting a resource.
The userID should be a session variable. Right. Pass the documentID in the querystring. Yup.
Assuming the documents are stored in the database, I would have a table for permissions: a recordID a userID and a documentID. You do a join with this table when calling up the document. If you don't get a result, you don't get the document. Index it all nicely and it will be fast.

Resources