Dynamic Restrictions Policy¶
The Dynamic Restriction Policy is designed for generic access control based on external security tables. It is available for selection in various restriction definition dialogs where a Custom View Policy can be chosen.
This policy generates dynamic restrictions by querying a specified security table (a Denodo view) and applying rules to the retrieved data. This allows for flexible and context-aware access control.
Parameters¶
The Dynamic Restriction Policy receives the following parameters during its configuration:
Database view name: The name of the Denodo database containing the view that serves as the security table.
View name: The name of the view used as the security table.
Policy rules: A JSON-formatted text defining a list of rules for generating restrictions. Tags may be used within the rule definitions, which will be resolved dynamically at runtime.
On rule absent: Defines the default restriction behavior when no policy rules generate restrictions (i.e., no rows from the security table match any rule, or no rules are defined). Valid options are:
ACCEPT: The query is accepted without any restrictions.
DENY: A privileges error accessing the view will be thrown.
REJECT: The rows which do not meet the generated condition will be excluded from the results.
MASKING: Masking is applied to sensitive fields, as defined in the policy rules.
Policy Rules (JSON Configuration)¶
The Policy rules parameter is a JSON text object containing the configuration for how the policy generates restrictions. It must include the following elements:
searchExpression: This is a condition applied to the WHERE clause when executing the specified Denodo view (View nameparameter). It filters the rows retrieved from the security table. It supports the use of predefined wildcards, which return data available from thecom.denodo.common.custom.policy.CustomRestrictionPolicyContextclass:@ELEMENT_DATABASE: The database of the element to which the custom policy is assigned.@ELEMENT_NAME: The name of the element to which the custom policy is assigned.@ELEMENT_TYPE: The type of the element to which the custom policy is assigned (e.g., ‘VIEW’, ‘STORED PROCEDURE’).@USER_AGENT: The user agent that executes the query.@USER_NAME: The name of the user executing the query.@USER_ROLES: The roles of the user to whom the policy is being checked.
Note
The value will be a text with the roles separated by commas which can be used with the
INoperator.@CREDENTIALS_NAME: The name of the credential to which the custom policy is assigned.@CREDENTIALS_TYPE: The type of credential to which the custom policy is assigned (e.g., ‘USER’, ‘ROLE’).
The
searchExpressionis modified based on the tags of the view specified as the security table. Tags present in the expression are replaced with the corresponding tagged field from the security view, if it exists.restriction: When creating a restriction, you need to specify its type. If no value is provided, the restriction defaults toREJECT. However, if you want to apply masking, you have two options:MASKING_IF_ANY_FIELD: This option applies masking if any of the fields specified insensitiveFieldsare present in the query’s selection list.MASKING_IF_ALL_FIELDS: This option applies masking only when all of the fields specified insensitiveFieldsare present in the query’s selection list.
sensitiveFields: This is a list of objects, required when therestrictiontype isMASKING. For each element in this list, you must provide:The name of the field (or tag) to be masked.
The masking expression to be applied to that field. Valid values are specified by
com.denodo.common.custom.policy.CustomMaskingExpressionand include:CUSTOM,DEFAULT,FIRST_4,HIDE,LATEST_4,ONLY_YEAR,REDACT,REDACT_ASTERISK,REMOVE_TIME,REMOVE_DAY,ROUND,SET_0,SET_MINUS_1. IfCUSTOMis selected, an additionalexpressionfield must be provided with the custom masking VQL expression.
The
sensitiveFieldslist is also modified based on the tags of the view used as the security table.rules: An array of rule definitions that define how the retrieved rows from the executed Denodo view (after applying thesearchExpression) are converted into restrictions enforced by the policy. Each rule consists of the following elements:antecedentCondition: A condition applied to the rows returned from the security table. If this condition is met for a given row, the rule is triggered.The
antecedentConditionis modified based on the tags of the view specified in the custom view policy.mappings: An array of objects defining how to extract data from the security table’s rows to be used in theconsequentCondition. Each mapping object has:key: The name of the field from the security table whose value will be assigned to the value variable. Tags can be also applied.value: The name of a variable to be used in theconsequentCondition.
consequentCondition: Specifies the condition that will be generated by this rule and added at runtime to the view involved in the query. This is the actual restriction applied.The
consequentConditionis modified based on the tags of the view to which the restriction is being applied.
Rule Logic:
When multiple rows from the security table match a single rule, the restrictions generated by each matching row for that rule are combined with an OR condition.
When Conditions are generated by different rules they are combined using AND conditions.
Note
Conditions used in
antecedentConditionandconsequentConditionmust not allow subqueries.
Policy Execution Flow¶
The custom policy dynamic_restrictions_policy executes the specified view (security table) as defined.
The searchExpression is added as a WHERE clause to this execution, filtering the rows from the security table.
Each tuple (row) returned after executing the security view with the searchExpression is matched against each defined rule in the rules array.
If the antecedentCondition of a rule is met by a tuple, the condition defined in the consequentCondition is generated. The mappings indicate how fields from the security view are used as values for variables in the consequentCondition.
Finally, the generated restrictions are returned by the custom view policy.
If no condition is generated by any rule (i.e., no rows match any rule), then the restriction defined by the On rule absent parameter is returned.
Examples¶
Consider the following example security and data tables:
Security Table¶ userid
sec_level
value
role_name
A123
WW
ALL
reader
A555
REGION
ASIA
editor
A555
SBE
HPA
reader
A432
REGION
ASIA
editor
A432
REGION
EU
reader
A111
SBE
HPA
reader
A111
SBE
PWR
editor
Data Table¶ id
sensitive_data
region
sbe
1
Only for Asia HPA
ASIA
HPA
2
Only for Asia PWR
ASIA
PWR
3
Only for Asia TPR
ASIA
TPR
4
Only for EU HPA
EU
HPA
5
Only for EU PWR
EU
PWR
6
Only for EU TPR
EU
TPR
7
Only for America PWR
America
PWR
8
Only for America HPA
America
HPA
9
Only for America TPR
America
TPR
REJECT Example¶
Let’s assume the user A555 queries a view. The policy will use the security table to determine restrictions.
Policy Configuration (JSON for Rules definition):
{
"searchExpression": "lower(userid_tag)=lower(@USER_NAME)",
"rules": [
{
"antecedentCondition": "sec_level_tag = 'REGION'",
"mappings": [
{
"key": "value",
"value": "region_value"
}
],
"consequentCondition": "region_tag = region_value"
},
{
"antecedentCondition": "sec_level_tag ='SBE'",
"mappings": [
{
"key": "value",
"value": "sbe_value"
}
],
"consequentCondition": "sbe_tag = sbe_value"
}
]
}
Explanation:
searchExpression:
lower(userid_tag)=lower(@USER_NAME)When user A555 queries, this translates to
lower(userid) = 'a555'when querying the Security table. This will retrieve rows for user A555.Default Restriction: REJECT:
The policy applies a REJECT restriction by default because none is provided.
First Rule (sec_level_tag = ‘REGION’):
The antecedent
sec_level_tag = 'REGION'matches the row whereuserId = 'A555'andsec_level = 'REGION'.The mapping
"key": "value", "value": "region_value"will then extract thevaluefield from this row, which is'ASIA'. This'ASIA'value is assigned to theregion_valuevariable.Consequently, the consequent
region_tag = region_valuebecomesregion_tag = 'ASIA'.Second Rule (sec_level_tag = ‘SBE’):
The antecedent
sec_level_tag = 'SBE'matches the row whereuserId = 'A555'andsec_level = 'SBE'.The mapping
"key": "value", "value": "sbe_value"will extract thevaluefield from this row, which is'HPA'. This'HPA'value is assigned to thesbe_valuevariable.As a result, the consequent
sbe_tag = sbe_valuebecomessbe_tag = 'HPA'.Combined Restriction:
Since both rules generate restrictions for user A555, these are combined with an AND condition. The final restriction applied to the query would be:
(region_tag = 'ASIA') AND (sbe_tag = 'HPA')This ensures that user A555 can only see data where the region field is ‘ASIA’ and the sbe field is ‘HPA’.
Result example 1¶ id
sensitive_data
region
sbe
1
Only for Asia HPA
ASIA
HPA
Roles-Based Filtering Example¶
This example demonstrates how to filter data based on a user’s assigned roles using the predefined @USER_ROLES wildcard. In this scenario, the user executing the query has been assigned the reader and unloader roles.
{
"searchExpression": "role_name IN (@USER_ROLES)",
"rules": [
{
"antecedentCondition": "sec_level_tag = 'REGION'",
"mappings": [
{
"key": "value",
"value": "region_value"
}
],
"consequentCondition": "region_tag = region_value"
}
]
}
Explanation:
searchExpression:
role_name IN (@USER_ROLES)The system substitutes @USER_ROLES with the user’s assigned roles. In this scenario, this results in the filter
role_name IN ('reader', 'unloader').First Rule (sec_level_tag = ‘REGION’):
The antecedent
sec_level_tag = 'REGION'matches the row wheresec_level = 'REGION'androle_name = 'reader'.The mapping
"key": "value", "value": "region_value"will then extract thevaluefield from this row, which is'EU'. This'EU'value is assigned to theregion_valuevariable.Consequently, the consequent
region_tag = region_valuebecomesregion_tag = 'EU'.Result example roles filtering¶ id
sensitive_data
region
sbe
4
Only for EU HPA
EU
HPA
5
Only for EU PWR
EU
PWR
6
Only for EU TPR
EU
TPR
MASKING Example¶
This example demonstrates how to apply masking to sensitive fields based on policy rules.
Policy Configuration (JSON for Policy rules):
{
"searchExpression": "lower(userid_tag)=lower(@USER_NAME)",
"restriction": "MASKING_IF_ANY_FIELD",
"sensitiveFields": [
{"tagged_field1":
{"type": "DEFAULT"}
},
{"tagged_field2":
{"type":"REDACT"}
},
{"tagged_field3":
{"type":"SET_0"}
},
{"tagged_field4": {
"type": "CUSTOM",
"expression": "HASH(tagged_field3)"}
}
],
"rules": [
{
"antecedentCondition": "sec_level_tag = 'REGION'",
"mappings": [
{
"key": "value",
"value": "region_value"
}
],
"consequentCondition": "region_tag = region_value"
}
]
}
Explanation:
searchExpression: Similar to the REJECT example, this filters the security table based on the current user. For this example, user A555 executes the query.
restriction: Set to
MASKING_IF_ANY_FIELD, meaning if any of the fields listed insensitiveFieldsare part of the query’s output, masking will be applied.sensitiveFields: Defines the fields that are considered sensitive and their respective masking expressions:
tagged_field1will use the default masking.Note
HIDEis the DEFAULT custom expression typetagged_field2will be redacted.tagged_field3will be set to 0.tagged_field4will be masked using a custom hash expression derived from the value of tagged_field3.
The
sensitiveFieldsare dynamically resolved based on the tags of the view to which the policy is applied. For more detailed information about row restrictions and masking expressions see Row Restrictions.rules: Similar to the REJECT example, these rules define conditions that, if met, will display the rows of the data table and mask the rows that do not meet the constraint. In this example the final restriction will be
region='ASIA'.Result example 2¶ id
sensitive_data
region
sbe
1
Only for Asia HPA
ASIA
HPA
2
Only for Asia PWR
ASIA
PWR
3
Only for Asia TPR
ASIA
TPR
********
0
8ubjub/1nyk/DpAZoeyrxQ==
********
0
8ubjub/1nyk/DpAZoeyrxQ==
********
0
8ubjub/1nyk/DpAZoeyrxQ==
********
0
CI8AODPVI9nczFKekpr9xw==
********
0
CI8AODPVI9nczFKekpr9xw==
********
0
CI8AODPVI9nczFKekpr9xw==
MASKING Example Affecting All Rows¶
This scenario shows how to mask sensitive data for users meeting the searchExpression, while allowing users not matching the searchExpression to see the data (due to On rule Absent: ACCEPT).
Policy Configuration:
On rule absent:
ACCEPT(configured outside the JSON rules, in the policy definition dialog)Policy Configuration (JSON for Policy rules):
{
"searchExpression": "lower(userid_tag)=lower(@USER_NAME)",
"restriction": "MASKING_IF_ANY_FIELD",
"sensitiveFields": [
{"sensitive_data":
{"type": "REDACT"}
}
],
"rules": [
{
"antecedentCondition": "1=1",
"mappings": [],
"consequentCondition": "1=0"
}
]
}
Explanation:
searchExpression:
lower(userid_tag)=lower(@USER_NAME). This will filter the security table for the current user.restriction:
MASKING_IF_ANY_FIELD, meaning sensitive fields will be masked.sensitiveFields:
sensitive_datais defined as a field to be redacted.rules:
antecedentCondition:1=1This condition is always true, meaning that for any row retrieved from the security table (after applying
searchExpression), this rule will always apply.consequentCondition:1=0This is a false condition. While this condition is technically generated, it acts as a placeholder that will never be met by any row in the data view. This effectively means that for users who trigger this rule, no data rows would satisfy the restriction. However, the purpose here is not to filter rows, but to trigger the masking.
Behavior for a user matching the searchExpression (e.g., user A555):
If the current user matches the
searchExpression, the policy will execute the security table query.Since
antecedentConditionis1=1, the rule will always be activated for any rows returned from the security table.The policy generates a restriction (even though it’s 1=0). The critical point is that a restriction is generated. Given the MASKING_IF_ANY_FIELD setting and the successful generation of a rule, the sensitive_data field will be redacted for all rows returned to this user, as the 1=0 condition effectively activates the masking behavior without filtering any data rows.
Result example 3 user A555¶ id
sensitive_data
region
sbe
1
********
ASIA
HPA
2
********
ASIA
PWR
3
********
ASIA
TPR
4
********
EU
HPA
5
********
EU
PWR
6
********
EU
TPR
7
********
America
HPA
8
********
America
PWR
9
********
America
TPR
Behavior for a user NOT matching the searchExpression (e.g., user B222):
If the current user does not match the
searchExpression, no rows will be returned from the security table after applying thesearchExpression.Consequently, no rules will be triggered, as their
antecedentConditioncannot be met by any rows from the (empty) result of the security table query.In this scenario, the On rule absent parameter comes into play. Since it’s explicitly set to
ACCEPT, the query will proceed without any restrictions, including no masking. The user will see all data from the view without any redactions.
Result example 3 user B222¶ id
sensitive_data
region
sbe
1
Only for Asia HPA
ASIA
HPA
2
Only for Asia PWR
ASIA
PWR
3
Only for Asia TPR
ASIA
TPR
4
Only for EU HPA
EU
HPA
5
Only for EU PWR
EU
PWR
6
Only for EU TPR
EU
TPR
7
Only for America HPA
America
HPA
8
Only for America PWR
America
PWR
9
Only for America TPR
America
TPR
