Saturday, March 16, 2024

 

Resource access control using row level security 

Resource access control using row level security

Introduction

How it works

References

​​

Introduction 

Some of the shortcomings in Infrastructure-as-code come directly from the resources in the public cloud that they manage. For example, a resource like key-vault allows access control via both role-based access control as well as access control policy and the IaC can specify but there is no built-in feature to allow selective access to secrets between users who are all granted access. Compare this with file-level security and additional checks can be placed on the individual files for enabling individual access control. This is a write-up on how to enable fine grained resource access control using row level security as borrowed from databases. It might be useful to consider non-differentiable resources with path-qualified files as names for their naming convention. Next, consider that we want to ACL them in the storage much the same way as we do files/folders on Windows with each file system entry pertaining to a key in the key-vault. Specifically, we allow for different permissions, grantee and even inheritance on resources/sub-resources that do not have primary built-in access control. 

 

How it works 

 Row level security in database is defined in the online documentation and comes with a readymade schema for such use - please see reference. In our case, we want to add a column/attribute/tag to our resource that is equivalent to the type of control that we want to apply to this resource. It could be a user name, or it could be a label or a foreign key to a set of markings that represent the sensitivity or the permissions of the data. 
Keeping track of usernames, for example, is helpful in the case where all accesses are directly isolated per user. In other words, users do not have to share the ownership of the folders and that their accesses are to manage the lifetime of their folders 
We can also create a label for each resource if we know that the labels are distinct and symbolic.  In most cases where the operations are predefined, but their actors are not, we can use different labels. For example, we can say whether the resource is read-only or read-write. 
However, users and their access are both dynamic and they can be hierarchical. In this case, hierarchical means that entries can inherit top down or gain incremental privileges bottom up. In addition, a user may grant or revoke permission, take ownership, etc. 
In such a case, it is better to view the labels as an output resulting from a schema of categories and markings. 
The categories and markings are predefined in a system. The categories represent a domain of markings. This can be a classification that is hierarchical or compartment that are distinct, they can be one-to-one or zero-to-many in how many values can be applied and may have a comparison rule - such as any or all.  The markings are the compartment or classification values we would like to division the resources into. Resources can belong to one or more of these. They can have a name. 

We may have only one category and one compartment. Categories can be hierarchical as in our case, but compartments are mutually exclusive. Note that the default or guest low privileged access corresponding to public marking may not be sufficient for security provisioning of all out of box features and hence it may need to be split or refined into more classifications. The classification hierarchy is expressed in the marking hierarchy table as opposed to the marking table. Next, we have the unique label table that assigns a unique label to a combination of markings and roles. 
Database roles will be at least one for each value of  any or all comparison rule of a non-hierarchical category. For hierarchical categories, again there will be one for each value, but the roles will also be nested. Some examples of roles are guest, dev, test, production support, reporting, owners, administrator, security administrator etc. 
When using label-based security model, it is important to note that the labels are assigned directly to each row of the base table. The labels are small, often a short byte or an integer and can have a non-clustered index on them. Sometimes, tags are not kept together in a base table but in a junction table of the base identifier and the label marking identifier. The reason this does not scale well is because it creates a duplicate column of the identifier. Moreover, if the identifier column is of type guid, then we cannot even build an index on them, and performance can suffer with scanning and full comparison between guids. Therefore, it is advisable to spend time and effort one time to add labels at the row level directly to the base table. 
A particular combination of markings could translate to a unique label for the resource. Usually, this table is populated on demand by say a stored procedure. If there is no corresponding row to the combination of markings, then a new row is added, and a unique ID is returned as the label. 
We join the label and mark in a LabelMarking table to facilitate the translation of the labels. 
A combination of markings can make up a permission. 

We continue this a little bit more by enumerating the access permissions as Full Control, Modify, Read & Execute, List folder contents, Read, Write and Special Permissions. We also define the built-in users and groups. Note that these permissions directly translate to the classifications mentioned earlier and hence the markings. Permissions can be granted or denied. Therefore, the markings must allow either of those states. Also note that the classification can be considered hierarchical. For example, a write may include a read. Similarly, a read and execute may include a read. Full control may include everything. Ownership and inheritance of resources are not mentioned in this section because they are more pertinent to users and groups. It is possible that only one security principal and/or group to be treated as the owner while others may have administrative access, therefore there is only one selection possible for owner but those do not belong in this schema because here we talk about permissions. 

Another thing is that the grant and the deny are mutually exclusive and this means that our markings will be different whether a permission is granted or denied. Moreover, distinct sets of markings can be attributed to different users and groups. This mapping between markings and user/group may need to be stored as well. The diverse types of markings possible are finite. The mapping between user/group and markings can be arbitrary and therefore exist as rows in the mapping table that maps markings between users and groups. In addition to having an owner, a resource can also be shared. Sharing means that other users/groups may have access to it. A default permission may be endowed with sharing. Something like 'write' for 'Everyone' may be considered implicit with sharing.

We concern ourselves with the resources only and not with the user / groups which is beyond the scope of this document. This is for two reasons: one that users/groups/roles are part of the role-based access security which is not in this scope and two we focus on resources only because we are concerned with granularity of the labels we can assign to the resources. Similarly, when we consider resources and permissions, we do not consider the attributes of the resources. If we take a resource as a path qualifier, there are certain other attributes possible. For example, a folder can be read-only or . den. It may be archive-able, compressed or encrypted. It may be a candidate for the contents to be indexed.

References 

MSDN: http://technet.microsoft.com/library/Cc966395 

Previous articles: IaCResolutionsPart93.docx

#codingexercise: CodingExercise-03-16-2024.docx

No comments:

Post a Comment