Exception-Based Policy Authoring
Prerequisite: Before using this walkthrough, please ensure that you’ve first done the Parts 1-5 of the POV Data Setup and the Schema Monitoring and Automatic Sensitive Data Discovery walkthrough.
Let’s draw an analogy. Imagine you are planning your wedding reception. It’s a rather posh affair, so you have a bouncer checking people at the door.
Do you tell your bouncer who’s allowed in? (exception-based) Or, do you tell the bouncer who to keep out? (rejection-based)
The answer to that question should be obvious, but many policy engines allow both exception- and rejection-based policy authoring, which causes a conflict nightmare. Ignoring that anti-pattern for a moment (which we’ll cover in the Anti-Pattern section) exception-based policy authoring in our wedding analogy means the bouncer has a list of who should be let into the reception. This will always be a shorter list of users/roles if following the principle of least privilege, which is the idea that any user, program, or process should have only the bare minimum privileges necessary to perform its function - you can’t go to the wedding unless invited. This aligns with the concept of privacy by design, the foundation of the CPRA and GDPR, which states “Privacy as the default setting.”
What this means in practice is that you should define what should be hidden from everyone, and then slowly peel back exceptions as needed.
Using an exception-based approach is a security standard across the board; this is because it’s a scalable approach that avoids costly data leaks and allows the business to move quickly. The “how” will be discussed in more detail in the Anti-Patterns section.
Because of this, the business reaps
- Increased revenue: accelerate data access / time-to-data.
- Decreased cost: operating efficiently at scale, agility at scale by building exceptions to agreed-upon foundational policies.
- Decreased risk: avoid data leaks by not conflating conflicting exception- and rejection-based policies.
Building an exception-based policy
Assumptions: Your user has the following permissions in Immuta (note you should have these by default if you were the initial user on the Immuta installation):
- GOVERNANCE: in order to build policy against any table in Immuta OR are a “Data Owner” of the registered tables (you likely are the Data Owner and have GOVERNANCE permission).
- USER_ADMIN: in order to manage groups/attributes on users.
Give yourself (and other users) attributes
We need to have attributes or groups assigned to you to drive policy. With Immuta these can come from anywhere (we mean literally anywhere), and Immuta will aggregate them to use in policy. Most commonly these come from your identity manager, such as LDAP, Active Directory, Okta, etc., but for simplicity sake, we are going to assign attributes to you in Immuta.
- Click the People icon and select Users in the left sidebar.
- Click your name.
- Click + Add Attributes.
- In the Add Attributes modal, enter Department in the Attribute field.
- Enter HR for Attribute value field.
- Repeat these steps for the non-admin user you created in Part 3 of the POV Data Setup. However, give that user the Attribute Department with the Attribute Value Analytics (instead of HR).
Build the exception-based policy
- In Immuta, visit the Fake HR Data data source (from any warehouse/compute).
- Go to the Data Dictionary tab and find where you have the
Discovered.Entity.Person Nametags. Let’s build a policy against that tag that includes an exception.
- Click the Policies icon in the left sidebar.
- Click + Add New Data Policy.
- Name it Mask Person Name.
- For action, select Mask.
- Leave columns tagged.
- Type in the tag
- Change masking type to using a constant.
- Type in the constant REDACTED.
- Leave for everyone except and change the exception to
- possesses attribute
- Click Add.
- Leave Where should this policy be applied? as is. (Immuta will guess correctly based on the previous steps.)
You can further refine where this policy is applied by adding another circumstance:
- Click + Add Another Circumstance.
- Change the or to an and.
- Select tagged for the circumstance. (Make sure you pick “tagged” and not “with columns tagged.")
- Type in Immuta POV for the tag name. (Remember, this was the tag you created in Schema Monitoring and Automatic Sensitive Data Discovery.) Note that if you are a Data Owner of the tables without GOVERNANCE permission the policy will be automatically limited to the tables you own.
- Click Create Policy and then Activate Policy.
Following the Query Your Data guide, test that your user sees the Person Name tagged columns in the clear, because you are part of Department HR and your non-admin user sees “REDACTED” for the same columns because they are not part of Department HR.
Let’s make this a little more complex. Let’s say that we want people in Department HR to see hashed names, but everyone else to see REDACTED. To do this, let’s update the policy:
- From the Policies page, click the menu button on the Mask Person Name policy we just created and click Edit.
- Click the three dot button on the actual policy definition and then select Edit. (Note you edit that separately because you can have multiple policy definitions in the single policy.)
- Change everyone except to everyone who.
- Change using a constant to using hashing in the first policy.
- Click Update.
- Click Save Policy.
Again, following the Query Your Data guide, test that your user sees the Person Name tagged columns now hashed, because you are part of Department HR and your non-admin user sees “REDACTED” for the same columns because they are not part of Department HR.
A key point to realize here is that when you did “everyone who” you were actually building a rejection-based policy, but to ensure there was no data leak, Immuta forced you to also have that catch-all OTHERWISE statement at the end, similar to a for-else in coding. This retains the exception-based concept to avoid a data leak.
How could your data leak if it wasn’t exception based?
What if you did two policies:
- Mask Person Name using hashing for everyone who possesses attribute Department HR.
- Mask Person Name using constant REDACTED for everyone who possesses attribute Department Analytics.
Now, some user comes along who is in Department finance - guess what, they will see the Person Name columns in the clear because they were not accounted for, just like the bouncer would let them into your wedding because you didn’t think ahead of time to add them to your deny list.
Again, fairly obvious: rejection-based policies are the Anti-Pattern and are completely contradictory to the industry standard of least privileged access; yet, for some reason, tools like Ranger rely on them and send users tumbling down this trap.
There are two main issues:
Ripe for data leaks: Rejection-based policies are extremely dangerous and why Immuta does not allow them except with a catch-all OTHERWISE statement at the end, which you walked through. Again this is because if a new role/attribute comes along that you haven’t accounted for, that data will be leaked. It is impossible for you to anticipate every possible user/attribute/group that could possibly exist ahead of time just like it’s impossible for you to anticipate any person off the street that could try to enter your posh wedding that you would have to account for on your deny list.
Ripe for conflicts and confusion: Tools that specifically allow both rejection-based and exception-based policy building create a conflict disaster. Let’s walk through a simple example, noting this is very simple, imagine if you have hundreds of these policies:
- Policy 1: mask name for everyone who is member of group A
- Policy 2: mask name for everyone except members of group B
What happens if someone is in both groups A and B? We have to fall back on policy ordering to avoid this conflict, which requires users to understand all other policies before building their policy and it is nearly impossible to understand what a single policy does without looking at all policies.
Feel free to return to the POV Guide to move on to your next topic.