Dynamic Policy Hooks in CDP
public class RangerCustomTagEnricher extends RangerAbstractContextEnricher {
…
@Override
public void enrich(RangerAccessRequest rangerAccessRequest) {
…
if (rangerAccessRequest != null && cacheUsersTag != null) {
Map<String, Object> context = rangerAccessRequest.getContext();
if (rangerAccessRequest.getUser() != null) {
String[] tags = cacheUsersTag.get(rangerAccessRequest.getUser());
if (context != null && tags != null) {
rangerAccessRequest.getContext().put(contextName, tags);
}
}
}
}
…
}
Once we have added this information to the context of the request, it is time to evaluate it in the isMatched method of the class that extends RangerAbstractConditionEvaluater .
In this case, since we don’t want to apply the masking policy if the user is tagged as dpo, we return false if we match the value the value set in the policy, true otherwise
public class RangerCustomTagEvaluator extends RangerAbstractConditionEvaluator{
…
public boolean isMatched(RangerAccessRequest rangerAccessRequest) {
boolean ret = true;
if (_allowAny) {
ret = false;
} else {
String[] requestValue = (String[]) rangerAccessRequest.getContext().get(_contextName);
if (requestValue != null) {
for (String policyValue: _values) {
if (ArrayUtils.contains(requestValue,policyValue)) {
ret = false;
break;
}
}
}
}
return ret;
}
The full code of both classes can be found here.
Once the code is compiled and a jar file is created, we have to put this jar into the hive classpath. In CDP we can copy the jar into the /opt/cloudera/parcels/CDH/lib/hive/lib/ranger-hive-plugin-impl/ directory and restart HiveServer2.
We will then register this Context Enricher and the Condition Evaluator using the Ranger API. We can first retrieve the service definition via a GET request to the Hive service definition:
#> curl -u admin:password123 -X GET https://$(hostname -f):6182/service/public/v2/api/servicedef/name/hive | tee hive_service.json
Then modify the hive_service.json file adding the following entries and pushing it back:
#> vi hive_service.json
…
"policyConditions": [
{
"itemId": 1,
"name": "USERTAG",
"evaluator": "com.dvergari.ranger.evaluator.RangerCustomTagEvaluator",
"evaluatorOptions": {
"attributeName": "USERTAG"
},
"label": "Exclude from condition",
"description": "Exclude Tag"
}
],
"contextEnrichers": [
{
"itemId": 1,
"name": "TagEnricher",
"enricher": "com.dvergari.ranger.enricher.RangerCustomTagEnricher",
"enricherOptions": {
"dbUrl": "jdbc:mysql://localhost/repository",
"username": "user",
"password": "password",
"table": "usertags"
}
}
],
…
#> curl -u admin:password123 -X PUT --data @hive_service.json -i -H 'Content-Type: application/json' https://$(hostname -f):6182/service/public/v2/api/servicedef/name/hive
In the enricherOptions field we added the information to connect to our MariaDB database.
If we connect again to Ranger, we can now see a new field “Policy Condition” where we can specify the tag for which not to apply the masking policy (dpo in our example):


Click on save and come back to beeline to check if it is working:
#> kinit bob
Password for bob@CLOUDERA.LOCAL:
#> beeline -e "select current_groups()as groups, c_last_name from tpcds_bin_partitioned_orc_5.customer limit 10" 2>/dev/null
+--------------------------+---------------------------------+
| groups | c_last_name |
+--------------------------+---------------------------------+
| ["bob","datascientist"] | 9c2d2409e88bb1351f690444e56c81 |
| ["bob","datascientist"] | c87bd09bf1868b0222e3ed7627069a |
| ["bob","datascientist"] | fac0505ae34b0e78b3a459606a24c3 |
| ["bob","datascientist"] | 1fc30d54c262e5502e1bff63e36420 |
| ["bob","datascientist"] | 721e5108bbf13544019ece1061c239 |
| ["bob","datascientist"] | 7569c3f1c51ef6c897c45b082f17c6 |
| ["bob","datascientist"] | 1b9c9f7f6877bfc15011e05df96067 |
| ["bob","datascientist"] | e42cacd863ebf10c6f425874b8eaf7 |
| ["bob","datascientist"] | 635f445b280626d97c548917fc5bc0 |
| ["bob","datascientist"] | 07908afd166b63b627eb616c6232de |
+--------------------------+---------------------------------+
#> kinit alice
Password for alice@CLOUDERA.LOCAL:
#> beeline -e "select current_groups()as groups, c_last_name from tpcds_bin_partitioned_orc_5.customer limit 10" 2>/dev/null
+----------------------------------------+---------------------------------+
| groups | c_last_name |
+----------------------------------------+---------------------------------+
| ["alice","developer","datascientist"] | 9c2d2409e88bb1351f690444e56c81 |
| ["alice","developer","datascientist"] | c87bd09bf1868b0222e3ed7627069a |
| ["alice","developer","datascientist"] | fac0505ae34b0e78b3a459606a24c3 |
| ["alice","developer","datascientist"] | 1fc30d54c262e5502e1bff63e36420 |
| ["alice","developer","datascientist"] | 721e5108bbf13544019ece1061c239 |
| ["alice","developer","datascientist"] | 7569c3f1c51ef6c897c45b082f17c6 |
| ["alice","developer","datascientist"] | 1b9c9f7f6877bfc15011e05df96067 |
| ["alice","developer","datascientist"] | e42cacd863ebf10c6f425874b8eaf7 |
| ["alice","developer","datascientist"] | 635f445b280626d97c548917fc5bc0 |
| ["alice","developer","datascientist"] | 07908afd166b63b627eb616c6232de |
+----------------------------------------+---------------------------------+
#> kinit davide
Password for davide@CLOUDERA.LOCAL:
#> beeline -e "select current_groups()as groups, c_last_name from tpcds_bin_partitioned_orc_5.customer limit 10" 2>/dev/null
+-----------------------------+-----------------------------------+
| groups | c_last_name |
+-----------------------------+-----------------------------------+
| ["davide","datascientist"] | Moran |
| ["davide","datascientist"] | Shipman |
| ["davide","datascientist"] | Gilbert |
| ["davide","datascientist"] | Williams |
| ["davide","datascientist"] | Grimes |
| ["davide","datascientist"] | Baker |
| ["davide","datascientist"] | Hernandez |
| ["davide","datascientist"] | Woods |
| ["davide","datascientist"] | Peterson |
| ["davide","datascientist"] | Fisher |
+-----------------------------+-----------------------------------+
As we can see now, also if bob, alice and davide belong to the same datascientist group, davide can now see the c_last_name column in clear, while bob and alice can’t.
Now let’s tag alice as dpo too:
#> mysql -u user -h localhost -ppassword repository
MariaDB [repository]> update usertags set taglist = 'dpo' where user = 'alice';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
And try again to select from hive:
#> kinit alice
Password for alice@CLOUDERA.LOCAL:
#> beeline -e "select current_groups()as groups, c_last_name from tpcds_bin_partitioned_orc_5.customer limit 10" 2>/dev/null
+----------------------------------------+---------------------------------+
| groups | c_last_name |
+----------------------------------------+---------------------------------+
| ["alice","developer","datascientist"] | Moran |
| ["alice","developer","datascientist"] | Shipman |
| ["alice","developer","datascientist"] | Gilbert |
| ["alice","developer","datascientist"] | Williams |
| ["alice","developer","datascientist"] | Grimes |
| ["alice","developer","datascientist"] | Baker |
| ["alice","developer","datascientist"] | Hernandez |
| ["alice","developer","datascientist"] | Woods |
| ["alice","developer","datascientist"] | Peterson |
| ["alice","developer","datascientist"] | Fisher |
+----------------------------------------+---------------------------------+
Now we can see also Alice has the right to select the c_last_name column in clear.



