# Advanced DSL Policy Builder Functions and Variables

There are several different advanced functions that are available for building subscription policies.

Users can create more complex policies using functions and variables in the advanced DSL policy builder than the policy builder allows. Data governors and owners can create global subscription policies using the functions and variables outlined below.

| Variable/function                                              | Description                                                                                                                           | Example                                                                                                                                                                                                                                                                                                                                                                                        |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @database                                                      | Users who have an attribute key that matches a database will be subscribed to the data source(s) within the database.                 | @hasAttribute('SpecialAccess', '@hostname.\@database'): If a user had the attribute `SpecialAccess: us-east-1-snowflake.default.*`, they would get subscribed to all the data sources in the `default` database.                                                                                                                                                                               |
| @hasAttribute('Attribute Name', 'Attribute Value')             | Users who have the specified attribute are subscribed to the data source.                                                             | @hasAttribute('Occupation', 'Manager'): Any user who has the attribute `Occupation` and the attribute key `Manager` will be subscribed to the data source(s).                                                                                                                                                                                                                                  |
| @hasTagAsAttribute('Attribute Name', 'dataSource' or 'column') | Users who have an attribute key that matches a tag on a data source or column will be subscribed to that data source.                 | @hasTagAsAttribute('PersonalData', 'dataSource'): Users who have the attribute key `PersonalData` with the values `Discovered.Passport`,`Discovered.Entity` would be subscribed to Data Source 1, which is tagged:`Discovered.Passport` and Data Source 2, which is tagged:`Discovered.Entity`. However, they would not be subscribed to Data Source 3, which is tagged: `Discovered.Country`. |
| @hasTagAsGroup('dataSource' or 'column')                       | Users who are members of a group that matches a tag on a data source or column (respectively) will be subscribed to that data source. | @hasTagAsGroup('dataSource'): If Data Source 1 has the tags `NewHire` and `Interns` applied, users who are members of the groups `New Hire` or `Interns` would be subscribed to Data Source 1.                                                                                                                                                                                                 |
| @hostname                                                      | Users who have an attribute key that match a hostname will be subscribed to the data source(s) with that hostname.                    | @hasAttribute('SpecialAccess', '@hostname'): If a user had the attribute `SpecialAccess : us-east-1-snowflake.*`, they would get subscribed to all the data sources with the `us-east-1-snowflake` hostname.                                                                                                                                                                                   |
| @isInGroups('List', 'of', 'Groups')                            | Users who are members of the specified group(s) can be subscribed to the data source.                                                 | @isInGroups('finance','marketing','newhire'): Users who are members of the groups `finance`, `marketing`, or `newhire` can be subscribed to the data source.                                                                                                                                                                                                                                   |
| @schema                                                        | Users who have an attribute key that match this schema will be subscribed to the data source(s) under that schema.                    | @hasAttribute('SpecialAccess', '@hostname.\@database.\@schema'): If a user had the attribute `SpecialAccess : us-east-1-snowflake.default.public`, they would get subscribed to all the data sources under the `public` schema.                                                                                                                                                                |
| @table                                                         | Users who have an attribute key that match this table will be subscribed to the data source(s).                                       | @hasAttribute('SpecialAccess', '@hostname.\@database.\@schema.\@table'): If a user had the attribute `SpecialAccess : us-east-1-snowflake.default.public.credit_transactions`, they would get subscribed to the `credit_transactions` data source.                                                                                                                                             |

{% hint style="warning" %}
It is not advisable to have thousands of distinct `@table` level permutations of access. That has an impact on how long policy resolution takes before pushing policies out to the data platform.
{% endhint %}

See the [Advanced DSL](https://documentation.immuta.com/saas/govern/secure-your-data/authoring-policies-in-secure/section-contents/how-to-guides/advanced-dsl-policies) tutorial for details on how to build a policy that includes advanced DSL.

## Orchestrated RBAC use cases

Some of these functions are narrowly focused on orchestrated RBAC use cases. Orchestrated RBAC is when an organization has many roles that represent access, and rather than switching to using the ABAC model provided by Immuta, they use these special functions to orchestrate existing roles using Immuta.

Specifically, the functions to enable orchestrated-RBAC are:

* `@hostname`
* `@database`
* `@schema`
* `@table`
* `@hasTagAsAttribute('Attribute Name', 'dataSource' or 'column')`
* `@hasTagAsGroup('dataSource' or 'column')`

### Example 1

Policy:

> `@hasAttribute('SpecialAccess', '@hostname.@database')`

User:

> has the attribute `SpecialAccess` with the value `us-east-1-snowflake.default`

The user would be subscribed to all the data sources in the `default` database. This has nothing to do with tags; it is based purely on the physical name of the host, database, schema, and table in the remote data platform.

### Example 2

Policy:

> `@hasTagAsAttribute('PersonalData', 'dataSource')`

User:

> has the attribute key `PersonalData` with the values
>
> * `Discovered.Person Name`
> * `Discovered.Entity`

Data source 1:

> tagged:
>
> * `Discovered.Country`
> * `Discovered.Passport`
> * `Discovered.Person Name`

Data source 2:

> tagged:
>
> * `Discovered.State`
> * `Discovered.Postal Code`
> * `Discovered.Entity.Social Security Number`

Data source 3:

> tagged:
>
> * `Discovered.State`
> * `Discovered.Passport`

The user would be subscribed to data source 1 and 2, but the user would not be subscribed to data source 3. This is because access moves from left-to-right in the hierarchy based on what the user possesses (the wildcard asterisk is implied).

So if a user had a more specific attribute key `PersonalData` with the values `Discovered.Entity.Social Security Number`, they would only get access to hypothetical data source 2, because their attribute is further left or matches (in this case matches) `Discovered.Entity.Social Security Number`.

The table below provides more examples:

| User Attributes                                               | Data Source Tags                                           | Subscribed? | Notes                                                                                                                                                                                     |
| ------------------------------------------------------------- | ---------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PersonalData`: `Discovered.Person Name`, `Discovered.Entity` | `Discovered.Identifier Indirect`, `Discovered.Person Name` | Yes         | Exact match on `Discovered.Person Name`                                                                                                                                                   |
| `PersonalData`: `Discovered.Entity`                           | `Discovered.PHI`, `Discovered.Entity.Age`                  | Yes         | User attribute `Discovered.Entity` is a hierarchical parent of data source tag `Discovered.Entity.Age`                                                                                    |
| `Access`: `Discovered.Person Name`, `Discovered.Entity`       | `Discovered.Identifier Indirect`, `Discovered.Person Name` | No          | The policy is written to only match values under the `PersonalData` attribute key. Not `Access`.                                                                                          |
| `PersonalData`: `Discovered`                                  | `Discovered.Entity.Age`                                    | Yes         | User attribute `Discovered` is a hierarchical parent of data source tag `Discovered.Entity.Age`                                                                                           |
| `PersonalData`: `Discovered.Entity.Social Security Number`    | `Discovered.Entity`                                        | No          | Hierarchical matching only happens in one direction (user attribute contains data source tag). In this case, the user attribute is considered hierarchical child of the data source tags. |

### Merging special functions

It is also possible to build subscription policies separately that use these special functions and have them merge on data sources.

This could be helpful for use cases with a policy like the following:

> If user has the attribute “Allowed\_Domain.Domain A” they get access to generic data that is part of domain A.
>
> If user has the attribute “Badge\_Allowed.Badge X” they should gain access to both “generic data + any additional data (only in domain A because they only have “Data Domain A General Access”) that has been tagged as “Badge X”.

In this case it can be two separate subscription policies, such as

Policy 1: `@hasTagAsAttribute(Allowed_Domain, ‘datasource’)` this would limit to the domains where they are allowed to see generic data.

Policy 2: `@hasTagAsAttribute(Badge_Allowed, ‘datasource’)` this would limit to the badges they are allowed to see.

Then, when the data sources are tagged with table tags that represent access, if the table only has the domain tag, only policy 1 will apply; however, if it has a domain tag and a badge tag, both policies will be applied and [merged successfully by Immuta](#user-content-fn-1)[^1].

### Use with caution

While this approach is extremely powerful, in many cases, it will continue to leave you dealing with policy complexity associated with RBAC. Read the [Governance use cases overview](https://documentation.immuta.com/saas/getting-started-with-secure#choose-your-path-orchestrated-rbac-or-abac) for more details.

[^1]: The way these policies merge depends on if it is a grant subscription policy or a guardrail subscription policy. See the [subscription policy overview page](https://documentation.immuta.com/saas/govern/secure-your-data/authoring-policies-in-secure/section-contents/subscription-policies#multiple-policies-on-a-single-data-source) for details.
