ABAC: Explorations and Concepts
Roles <> Permissions for ABAC at various touch points
Policy Application Model Comparison
We need to evaluate three different models for implementing attribute-based access control (ABAC) policies in Mattermost. Each model is applied to three user stories with detailed policy setups.
Model 1:
Multiple (rules x permissions) sets within the same policy, applied together with the ‘OR’ operator
Only 1 policy can be applied to a channel at a time
Note: Since no channel can have more than one policy under Model 1, so all access criteria for that channel must be encapsulated in one policy. This model emphasizes one comprehensive policy per channel, potentially with many OR branches.
Model 2:
Simple policies with 1 (rules x permissions) set within a policy
Multiple policies can be applied to a channel, resolved with the ‘OR’ operator
Note: Model 2 is analogous to how cloud IAM typically works: multiple attached policies each contribute permissions; the user’s total access is the union of what all satisfied policies allow. There is no built-in concept of requiring all policies to match.
Model 3:
Multiple (rules x permissions) sets within the same policy, applied together with the ‘OR’ operator
Multiple policies can be applied to a channel, resolved with the AND operator
Note: The crucial difference is that in Model 3, when more than one policy is attached to a channel, they are combined with logical AND. This means a user must satisfy all the attached policies’ conditions (at least for the relevant actions) in order to be granted access. In effect, each policy can represent one required facet of access, and a user is only allowed if they meet every policy’s criteria. This is a form of policy intersection – much like requiring multiple gatekeepers to all approve. (It’s somewhat analogous to AWS IAM’s permissions boundaries or Service Control Policies, where an action must be allowed by both the identity policy and the boundary to be permitted.) Within each individual policy, multiple rules can still provide OR logic for that facet. This is also consistent with how we were planning to apply Custom Channel Access Rules along with an Access Policy.
Below, we evaluate each model against the user stories, check for any failure points, and discuss complexity or anti-pattern issues.
User Story 1 – “Clearance-Based Access in Team A”
Requirement: All users with a Clearance attribute of Confidential, Secret, or TopSecret should be able to join and post in any channel in Team A. However, only users with Secret or TopSecret clearance can upload/download files in those channels. Users with only Confidential clearance should not be able to share files.
Model 1
Policy Implementation: Under Model 1, the example policy for all Team A channels is “Clearance for All Channels”. This single policy uses two OR rule sets to cover the requirement. Model 1’s policy as shown does satisfy User Story 1’s requirements
Potential Pitfalls: Although the policy itself works, Model 1 could become cumbersome if many attribute conditions must be packed into one policy. For this simple clearance scenario, it’s fine.
Model 2
Policy Implementation: In the Model 2 example, the single Model 1 policy is split into two smaller policies:
Policy 1: “Confidential Access” – This policy has one rule: If
user.clearance == Confidential
(or possibly “≥ Confidential”), then allow membership and posting in the channel. It effectively grants basic access to users with Confidential clearance. (It might actually consider Confidential as one specific value; users with higher clearance might not match this condition exactly – more on that below).Policy 2: “S-TS Access” – A second policy with one rule: If
user.clearance ∈ {Secret, TopSecret}
, then allow all channel permissions (including file operations).
Notable Difference from Model 1: Model 2’s approach is more modular – each policy is simpler (single condition, specific permission set). This can be easier to read and reason about in isolation (each policy has a clear purpose). However, understanding the total access on a channel requires considering the OR combination of multiple policies. In Story 1’s case it’s straightforward, but it sets the stage for more complexity in the next stories.
Model 3
Policy Implementation: The simplest way to implement Story 1 in Model 3 would actually be similar to Model 1 (since AND isn’t needed for just clearance logic).
User Story 2 – “Program-Based Access to Project Channels”
Requirement: In addition to the above clearance rules, certain channels (those related to a specific project “DragonSpacecraft”) should only be accessible to users who are members of that program, but only those members with a military Rank of Major (or higher) can upload/download files in those channels.
Model 1
Policy Implementation: Under Model 1’s one-policy-per-channel rule, we cannot attach a separate “program membership” policy to a channel in addition to the clearance policy – everything must be combined. This means the channels associated with DragonSpacecraft require a dedicated policy that merges both the clearance classification rules and the program membership & rank rules.
Complexity & Anti-Patterns: This scenario exposes a complexity of Model 1: the policy becomes a monolithic rule set, mixing multiple attributes and conditions. It’s powerful, but not modular. Each special case (like the DragonSpacecraft channels) requires creating a bespoke policy or heavily parameterizing a generic one. Reusing the same policy for all channels might not be possible if some channels have extra conditions – you’d need separate policies (one per variation). That could lead to policy proliferation (one policy for regular channels, another for project channels, another for some other case, etc.), and each policy is complex. Maintaining such large policies can be error-prone; the flexibility of ABAC can lead to very complex rules that are “difficult to handle and understand”. Model 1 essentially encourages writing one big boolean rule set per channel (or per channel type), which can become an anti-pattern if policies are copy-pasted and slightly tweaked for each new scenario. Inconsistent updates and difficulty verifying each OR branch are risks here.
Model 2
Policy Implementation: With Model 2, we have the ability to attach multiple policies, but they all combine as OR. This is tricky because Story 2’s requirements involve an AND combination of conditions (must be in program and have clearance for membership; must have rank and clearance for file). Therefore, to meet the Story 2 needs, we’ll need two new policies applying to DragonSpacecraft channels, and we need to make sure those channels are not a part of our original policies anymore.
Complexity & Anti-Patterns: Model 2 introduces modularity at the cost of potential mis-ordering. Authors have to carefully design each small policy and attach the right combination. One anti-pattern to avoid is thinking that attaching two policies creates an AND requirement. It does not – it’s always OR (the user can come in via any one policy’s rule). This model aligns with standard IAM paradigms like AWS IAM and Azure RBAC, where multiple role/policy assignments each grant privileges and a user’s permissions are the union of all grants. That alignment is good (familiar to many), but it means policy writers must encode multi-attribute requirements into single policies (via multiple conditions in one rule) rather than splitting them. The example we gave above does that correctly. From a UX perspective, policy authors using Model 2 might find it simpler to reason about one condition per policy, but when a scenario truly needs an intersection of attributes, they might initially be tempted to split conditions into separate policies (leading to mistakes). Proper guidance and possibly UI warnings are needed to prevent that.
Summary of Model 2 Issues: Model 2 improves readability at the individual policy level and aligns with common IAM (policies are independent, combined additively). But it has potential anti-patterns like policy fragmentation (too many granular policies) and OR-logic pitfalls (accidentally granting access via one policy that was meant to be combined with another). Policy authors must be vigilant about crafting conditions properly and attaching policies only where appropriate.
Model 3
Policy Implementation: Model 3 shines for scenarios requiring multiple conditions. Instead of combining program and clearance in one rule (as we had to in Model 2), we can make separate policies and attach both, relying on the AND requirement to enforce that both conditions are met.
This approach clearly satisfies Story 2 and does so in a way that is arguably cleaner logically: each policy is focused on one aspect (program membership, classification level, rank for files). The AND combination ensures all aspects are simultaneously required. This is something Model 2 could not do without combining conditions into one policy – Model 3 achieves it by policy stacking.
Anti-Patterns & Complexity: Model 3’s approach clearly addresses multi-conditional requirements elegantly (each condition isolated). However, it is extremely complex to reason about. For an admin, understanding that “user must satisfy Policy A AND Policy B AND Policy C” is fine in theory, but when each policy might itself have internal OR rules, the logic is not transparent. It’s easy to misjudge the effect of adding a policy. For example, if an admin wants to tighten security, they might attach an extra policy to a channel thinking “this will add another requirement,” which it does – but if that requirement is unnecessary or mis-scoped, it could lock everyone out. Conversely, removing one policy from the stack could suddenly open a hole (making something optional that was supposed to be required).
In terms of alignment with best practices: Model 3 is quite unique. It resembles theoretical ABAC frameworks or maybe certain resource-permission boundary concepts, but it’s not how mainstream RBAC/ABAC systems present to users. For example, AWS does allow layering policies but always OR for allows (AND only comes via a deny or boundary which is a specialized use). Azure AD roles combine permissively as well. The AND approach might align with more formal models (e.g., the idea of policy sets in XACML requiring all sub-policies to permit), but those are seldom exposed to end-users because of the complexity.
User Story 3 – “Device Trust Requirement for ERT Members”
Requirement: Building on the above scenarios, the third story adds that Emergency Response Team (ERT) members are allowed to upload/download files but only when using “DoD_Managed” secure devices. This is in addition to all earlier restrictions (clearance and program rules still apply otherwise).
Model 1
Policy Implementation: Under Model 1, again a single policy must handle this. Likely, all policies for used for all channels would be extended with another OR rule addressing the ERT case. This is in addition to all earlier restrictions (clearance and program rules still apply otherwise).
This is in addition to all earlier restrictions (clearance and program rules still apply otherwise).
However, adding this rule further increases the complexity of the policy. Now the single policy is controlling access based on three factors: clearance level, program membership + rank (for certain channels), and device trust for ERT. Writing and mentally validating all combinations of these within one OR-heavy policy is quite complex.
Complexity & Anti-Patterns: Model 1 at this stage has a very complex single policy (especially for channels like the #dragon ones that have the program constraint as well). This is arguably an anti-pattern in IAM design – policies that encode many conditions become difficult to read and manage. They violate the principle of separation of concerns; ideally, one would like to separate device trust checks from clearance checks, etc., for clarity. In Model 1, that’s impossible without breaking the one-policy rule. As policies grow, misconfigurations become more likely because an admin might accidentally modify one branch and impact others. The ABAC flexibility “makes it possible to have very complex policies, which makes them difficult to handle and understand”permify.co. Model 1 is prone to this pitfall as more attributes get rolled in. It can satisfy all the user stories in theory, but at the cost of policy readability and maintainability.
Summary of Model 1 Issues: Despite being conceptually simple (each channel = one policy), Model 1’s approach can lead to monolithic policies that are hard to author correctly. Anti-patterns include repeating similar conditions across many policies (if each channel gets its own version) and mixing unrelated checks in one place. It goes somewhat against the grain of IAM best practices that suggest breaking up policies for claritydocs.aws.amazon.com. There is also limited flexibility – you cannot mix and match small policy components; every scenario needs a unique OR logic concoction in a single policy.
Model 2
Policy Implementation: For the ERT device-based exception, in Model 2 we can create a separate policy to grant file permissions to ERT members on DoD_Managed devices, and attach that policy to channels. Because the combination is OR, this new policy would act as an additional route to file access.
This aspect of Model 2’s OR nature – it’s easy to add an exception: just attach another permissive policy for that exception. It won’t take away permissions from anyone else (unless you inadvertently alter other policies).
Complexity & Anti-Patterns: Model 2 handled this new requirement by simply adding one more policy. That’s both a strength and a potential weakness. It’s a strength because it isolates the new logic (ERT on managed device) in its own policy – clean and modular. We didn’t have to edit existing policies (avoiding risk of breaking them); we just bolted on a new piece. This is analogous to how one might attach an additional AWS IAM policy to an identity for a special case. The flip side is that now each channel might have, say, three or more policies attached (Clearance, maybe Program, maybe Device exceptions, etc.). As the number of policies grows, tracking which policies apply where becomes harder. The policy list for a channel could become long, and understanding the net effect requires scanning all of them.
A notable best practice alignment: Model 2’s approach of multiple OR-combined policies aligns well with AWS/Azure style role-based and attribute-based policies. In AWS IAM, for instance, you might have one policy for base access and another for elevated access, both attached to a user or role; the user gets both sets of permissions if conditions are metdocs.aws.amazon.com. AWS recommends grouping permissions functionally (e.g., separate policies for separate concerns)docs.aws.amazon.com, which is exactly what we see here: clearance rules in one policy, device trust in another, etc. This improves policy readability since each policy addresses a single concern (e.g., “this policy is clearly about device requirements for file actions”). The trade-off is the potential sprawl of many such policies and the need for a good UX to manage policy attachments.
Summary of Model 2: Model 2 satisfies all user stories by composing multiple focused policies per channel. It offers simplicity at the individual policy level, better reuse, and familiar OR semantics. However, it introduces complexity in composition: authors must manually ensure that the right combination of policies (with correctly formulated conditions) are attached to each channel. The risk of misconfiguration is moderate – mainly from accidentally giving an OR path that bypasses a required attribute. With careful design (each policy’s condition encoding all needed attributes for that permission), this risk is mitigated. Over time, the scalability in terms of number of policies can be an issue, and managing many small pieces might become burdensome.
Model 3
Policy Implementation: The approach in Model 3 would be to incorporate the ERT condition into all existing policies giving file permissions to ERT members using DoD Managed devices as an alternative rule. This somewhat defeats the “pure” separation of policies for each attribute and highlights that Model 3, while flexible, can force mixing conditions anyway to handle exceptions, or else suffer unintended restrictions.
Complexity & Anti-Patterns: Model 3 in Story 3 becomes unwieldy. The interplay of multiple policies and needing to adjust their internal logic for exceptions is complex and the mental model required is more complicated than typical IAM. Every time you attach a policy, you must ask “am I requiring this condition of everyone?” If not, maybe it doesn’t belong as a separate policy.
Alignment with standards: As noted, mainstream IAM does not typically use an AND combine at the resource level for allow rules. Model 3 is more aligned with academic or high-security policy models (where you might, say, have a system of “you must satisfy location policy AND role policy AND device policy”). Some systems achieve a similar effect via separate layers (e.g., an application might enforce location separately from role), but seldom via user-facing policy attachments.
Summary of Model 3: This model can theoretically implement very complex policies by breaking them into components, and it did meet the core requirements of the user stories when configured carefully. However, it comes at a cost in UX simplicity and risk of misconfiguration.
It’s at the top of ABAC complexity: “multiple policies work together to make complex decisions” – powerful but difficult to manage correctly
Dimension | Model 1: Single Policy/Channel (OR-internal) | Model 2: Multi-Policy OR (Additive) | Model 3: Multi-Policy AND (Intersection) |
---|---|---|---|
UX Simplicity for Authors | ✔ Simple conceptual model ✘ Authoring complexity grows as rules multiply. ✘ Writing complex boolean logic in one policy is hard. ✘ No modular reuse; each channel’s policy might be a one-off. | ✔ Modular policies – easier to write and reason about individually. ✔ Can mix and match policies on a channel. ✘ Composition is implicit (OR) – Authors must understand that attaching multiple policies creates an OR. | ✘ Complex mental model – Authors must manage multiple policies and understand that all attached must be satisfied. ✘ The model is powerful but not beginner-friendly. |
Scalability for Complex Use Cases | ✘ Does not scale elegantly – Complex scenarios lead to giant policies with many OR branches. ✘ Different channels often need distinct policies, leading to potential duplication. ✔ Performance – (Likely acceptable for moderate complexity, since it’s one policy eval per access, albeit with many rules.) | ✔ Scales moderately – You can handle complexity by adding more policies (instead of bloating one). Policies can be reused across multiple channels, reducing duplication. ✘ Policy explosion – A very complex scenario might require many small policies; managing and curating those at scale can get difficult. | ✔ Highly flexible logic – Can express virtually any combination of conditions (AND/OR) by appropriate policy splits. ✔ Good for very complex, multi-attribute requirements. ✘ Administrative scalability is poor – The number of policies and intricacy of their interplay can grow out of hand. |
Alignment w/ Standard IAM Paradigms | ◑ Partial alignment – Similar to having one resource-based policy with multiple statements. It’s a valid approach, but modern IAM (AWS/Azure) usually allows multiple policies. | ✔ Strong alignment – Mirrors how cloud IAM typically works (multiple policies, each with one statement/condition, combine permissively). AWS IAM, for example, evaluates multiple attached policies as a logical OR, and encourages grouping permissions by function. | ✘ Misaligned with common IAM – Few mainstream systems use an AND combination of allows. This is closer to advanced policy frameworks (XACML’s policy combining, or IAM permission boundaries concept where two sets of conditions must simultaneously allow an action). It’s powerful but unusual for everyday policy management. |
Policy Readability | ✘ Low readability when complex – A simple policy is easy to read, but once it contains many OR rules for different cases, it becomes like reading a long logic expression. | ✔ High readability of each policy – Each small policy tends to be straightforward (“If X then allow Y”). This clarity at the micro level aids understanding. ◑ Moderate readability at channel level – To fully understand a channel’s access, you must read all attached policies and remember they are OR-ed. Good naming and documentation of policies become important so one can tell at a glance. | ✘ Poor readability – Neither each policy alone nor the combination is easy to grok without formal analysis. Each policy might be simple, but knowing that all of them together define access requires mentally intersecting their conditions. |