0
# Context Enrichment
1
2
Pluggable context enrichment framework for enhancing access requests with additional attributes for policy evaluation. Context enrichers add dynamic information to access requests such as tags, user attributes, geographical location, time-based data, and other contextual information that policies can use for fine-grained access control decisions.
3
4
## Capabilities
5
6
### RangerContextEnricher
7
8
Core interface for context enrichment components that add attributes to access requests during policy evaluation.
9
10
```java { .api }
11
/**
12
* Interface for context enrichment components
13
*/
14
public interface RangerContextEnricher {
15
/**
16
* Initialize the context enricher with configuration
17
*/
18
public void init();
19
20
/**
21
* Enrich the access request with additional context
22
* @param request - Access request to enrich with context
23
*/
24
public void enrich(RangerAccessRequest request);
25
26
/**
27
* Check if this enricher needs dynamic evaluation
28
* @return True if dynamic evaluation is required
29
*/
30
public boolean preCleanup();
31
32
/**
33
* Cleanup resources after enrichment
34
*/
35
public void cleanup();
36
}
37
```
38
39
### RangerAbstractContextEnricher
40
41
Abstract base class providing common functionality for context enrichers, including configuration management and lifecycle support.
42
43
```java { .api }
44
/**
45
* Abstract base implementation for context enrichers
46
*/
47
public abstract class RangerAbstractContextEnricher implements RangerContextEnricher {
48
/**
49
* Enricher definition from service definition
50
*/
51
protected RangerContextEnricherDef enricherDef;
52
53
/**
54
* Service definition this enricher belongs to
55
*/
56
protected RangerServiceDef serviceDef;
57
58
/**
59
* Application ID for this enricher
60
*/
61
protected String appId;
62
63
/**
64
* Initialize the abstract context enricher
65
* @param enricherDef - Enricher definition
66
* @param serviceDef - Service definition
67
* @param appId - Application identifier
68
*/
69
public void init(RangerContextEnricherDef enricherDef, RangerServiceDef serviceDef, String appId);
70
71
/**
72
* Get enricher configuration options
73
* @return Map of configuration options
74
*/
75
public Map<String, String> getOptions();
76
77
/**
78
* Get a specific configuration option
79
* @param name - Option name
80
* @return Option value or null if not found
81
*/
82
public String getOption(String name);
83
84
/**
85
* Get a configuration option with default value
86
* @param name - Option name
87
* @param defaultValue - Default value if option not found
88
* @return Option value or default value
89
*/
90
public String getOption(String name, String defaultValue);
91
92
/**
93
* Get a boolean configuration option
94
* @param name - Option name
95
* @param defaultValue - Default value if option not found
96
* @return Boolean option value or default value
97
*/
98
public boolean getBooleanOption(String name, boolean defaultValue);
99
100
/**
101
* Get an integer configuration option
102
* @param name - Option name
103
* @param defaultValue - Default value if option not found
104
* @return Integer option value or default value
105
*/
106
public int getIntOption(String name, int defaultValue);
107
108
/**
109
* Get a long configuration option
110
* @param name - Option name
111
* @param defaultValue - Default value if option not found
112
* @return Long option value or default value
113
*/
114
public long getLongOption(String name, long defaultValue);
115
116
/**
117
* Get the enricher name
118
* @return Enricher name
119
*/
120
public String getEnricherName();
121
122
/**
123
* Get the service name
124
* @return Service name
125
*/
126
public String getServiceName();
127
128
/**
129
* Get the service type
130
* @return Service type
131
*/
132
public String getServiceType();
133
134
/**
135
* Default implementation - no pre-cleanup needed
136
* @return False by default
137
*/
138
@Override
139
public boolean preCleanup();
140
141
/**
142
* Default implementation - no cleanup needed
143
*/
144
@Override
145
public void cleanup();
146
}
147
```
148
149
### RangerTagEnricher
150
151
Context enricher that adds tag-based attributes to access requests for attribute-based access control (ABAC).
152
153
```java { .api }
154
/**
155
* Context enricher for tag-based attributes
156
*/
157
public class RangerTagEnricher extends RangerAbstractContextEnricher {
158
/**
159
* Key for storing tags in request context
160
*/
161
public static final String TAG_ATTR_SET_KEY = "TAGS";
162
163
/**
164
* Key for storing tag-based policies in context
165
*/
166
public static final String TAG_POLICIES_KEY = "TAG_POLICIES";
167
168
/**
169
* Initialize the tag enricher
170
*/
171
@Override
172
public void init();
173
174
/**
175
* Enrich access request with tag information
176
* @param request - Access request to enrich
177
*/
178
@Override
179
public void enrich(RangerAccessRequest request);
180
181
/**
182
* Get tags for a specific resource
183
* @param resource - Resource to get tags for
184
* @return Set of tags associated with the resource
185
*/
186
public Set<RangerTagForEval> getTagsForResource(RangerAccessResource resource);
187
188
/**
189
* Get all tags for resource matching
190
* @return List of all available tags
191
*/
192
public List<RangerTag> getTags();
193
194
/**
195
* Get service tags configuration
196
* @return Service tags configuration
197
*/
198
public ServiceTags getServiceTags();
199
200
/**
201
* Update service tags configuration
202
* @param serviceTags - New service tags configuration
203
*/
204
public void setServiceTags(ServiceTags serviceTags);
205
206
/**
207
* Get tag policies for evaluation
208
* @return List of tag-based policies
209
*/
210
public List<RangerPolicy> getTagPolicies();
211
212
/**
213
* Check if tag enricher is enabled
214
* @return True if tag enricher is enabled
215
*/
216
public boolean isTagEnricherEnabled();
217
218
/**
219
* Get tag attribute evaluators
220
* @return Map of attribute names to evaluators
221
*/
222
public Map<String, RangerTagAttributeEvaluator> getTagAttributeEvaluators();
223
}
224
```
225
226
### RangerUserStoreEnricher
227
228
Context enricher that adds user and group attribute information to access requests.
229
230
```java { .api }
231
/**
232
* Context enricher for user and group attributes
233
*/
234
public class RangerUserStoreEnricher extends RangerAbstractContextEnricher {
235
/**
236
* Key for storing user attributes in context
237
*/
238
public static final String USER_ATTRIBUTES_KEY = "USER_ATTRIBUTES";
239
240
/**
241
* Key for storing group attributes in context
242
*/
243
public static final String GROUP_ATTRIBUTES_KEY = "GROUP_ATTRIBUTES";
244
245
/**
246
* Initialize the user store enricher
247
*/
248
@Override
249
public void init();
250
251
/**
252
* Enrich access request with user and group attributes
253
* @param request - Access request to enrich
254
*/
255
@Override
256
public void enrich(RangerAccessRequest request);
257
258
/**
259
* Get user attributes
260
* @param userName - Username to get attributes for
261
* @return Map of user attributes
262
*/
263
public Map<String, String> getUserAttributes(String userName);
264
265
/**
266
* Get group attributes
267
* @param groupName - Group name to get attributes for
268
* @return Map of group attributes
269
*/
270
public Map<String, String> getGroupAttributes(String groupName);
271
272
/**
273
* Get all users in user store
274
* @return Set of all usernames
275
*/
276
public Set<String> getAllUsers();
277
278
/**
279
* Get all groups in user store
280
* @return Set of all group names
281
*/
282
public Set<String> getAllGroups();
283
284
/**
285
* Get groups for a specific user
286
* @param userName - Username to get groups for
287
* @return Set of group names for the user
288
*/
289
public Set<String> getGroupsForUser(String userName);
290
291
/**
292
* Update user store configuration
293
* @param userStore - New user store configuration
294
*/
295
public void setUserStore(RangerUserStore userStore);
296
297
/**
298
* Get current user store configuration
299
* @return Current user store configuration
300
*/
301
public RangerUserStore getUserStore();
302
303
/**
304
* Check if user store enricher is enabled
305
* @return True if user store enricher is enabled
306
*/
307
public boolean isUserStoreEnricherEnabled();
308
}
309
```
310
311
### RangerScriptEnricher
312
313
Context enricher that allows custom script-based context enrichment for advanced use cases.
314
315
```java { .api }
316
/**
317
* Script-based context enricher for custom enrichment logic
318
*/
319
public class RangerScriptEnricher extends RangerAbstractContextEnricher {
320
/**
321
* Configuration key for script engine type
322
*/
323
public static final String SCRIPT_ENGINE_TYPE = "script.engine.type";
324
325
/**
326
* Configuration key for script content
327
*/
328
public static final String SCRIPT_CONTENT = "script.content";
329
330
/**
331
* Configuration key for script file path
332
*/
333
public static final String SCRIPT_FILE_PATH = "script.file.path";
334
335
/**
336
* Default script engine type (JavaScript)
337
*/
338
public static final String DEFAULT_SCRIPT_ENGINE = "javascript";
339
340
/**
341
* Initialize the script enricher
342
*/
343
@Override
344
public void init();
345
346
/**
347
* Enrich access request using custom script logic
348
* @param request - Access request to enrich
349
*/
350
@Override
351
public void enrich(RangerAccessRequest request);
352
353
/**
354
* Get the script engine being used
355
* @return Script engine instance
356
*/
357
public ScriptEngine getScriptEngine();
358
359
/**
360
* Get the script content
361
* @return Script content as string
362
*/
363
public String getScriptContent();
364
365
/**
366
* Load script from file
367
* @param filePath - Path to script file
368
* @return Script content
369
* @throws IOException if file cannot be read
370
*/
371
public String loadScriptFromFile(String filePath) throws IOException;
372
373
/**
374
* Execute script with given parameters
375
* @param params - Parameters to pass to script
376
* @return Script execution result
377
* @throws ScriptException if script execution fails
378
*/
379
public Object executeScript(Map<String, Object> params) throws ScriptException;
380
}
381
```
382
383
### RangerGeolocationEnricher
384
385
Context enricher that adds geographical location information based on client IP address.
386
387
```java { .api }
388
/**
389
* Context enricher for geographical location information
390
*/
391
public class RangerGeolocationEnricher extends RangerAbstractContextEnricher {
392
/**
393
* Key for storing country information in context
394
*/
395
public static final String GEO_COUNTRY_KEY = "GEO_COUNTRY";
396
397
/**
398
* Key for storing state/province information in context
399
*/
400
public static final String GEO_STATE_KEY = "GEO_STATE";
401
402
/**
403
* Key for storing city information in context
404
*/
405
public static final String GEO_CITY_KEY = "GEO_CITY";
406
407
/**
408
* Configuration key for geolocation database path
409
*/
410
public static final String GEO_DB_PATH_CONFIG = "geo.db.path";
411
412
/**
413
* Configuration key for enabling geolocation enrichment
414
*/
415
public static final String GEO_ENABLED_CONFIG = "geo.enabled";
416
417
/**
418
* Initialize the geolocation enricher
419
*/
420
@Override
421
public void init();
422
423
/**
424
* Enrich access request with geographical location information
425
* @param request - Access request to enrich
426
*/
427
@Override
428
public void enrich(RangerAccessRequest request);
429
430
/**
431
* Get geographical location for an IP address
432
* @param ipAddress - IP address to lookup
433
* @return Geographical location information
434
*/
435
public GeoLocation getLocationForIP(String ipAddress);
436
437
/**
438
* Check if geolocation database is available
439
* @return True if geolocation database is loaded and available
440
*/
441
public boolean isGeolocationAvailable();
442
443
/**
444
* Update geolocation database
445
* @param dbPath - Path to new geolocation database file
446
* @throws IOException if database cannot be loaded
447
*/
448
public void updateGeolocationDatabase(String dbPath) throws IOException;
449
}
450
```
451
452
### Context Enrichment Helper Classes
453
454
Helper classes and data structures used by context enrichers.
455
456
```java { .api }
457
/**
458
* Container for tag evaluation information
459
*/
460
public class RangerTagForEval {
461
/**
462
* Get the tag type
463
* @return Tag type name
464
*/
465
public String getType();
466
467
/**
468
* Get tag attributes
469
* @return Map of attribute names to values
470
*/
471
public Map<String, String> getAttributes();
472
473
/**
474
* Get tag matching information
475
* @return Tag matching details
476
*/
477
public RangerTagMatchInfo getMatchInfo();
478
479
/**
480
* Check if tag matches the resource
481
* @param resource - Resource to check against
482
* @return True if tag applies to resource
483
*/
484
public boolean isApplicable(RangerAccessResource resource);
485
}
486
487
/**
488
* Evaluator for tag attributes
489
*/
490
public class RangerTagAttributeEvaluator {
491
/**
492
* Evaluate tag attribute value
493
* @param request - Access request
494
* @param tag - Tag being evaluated
495
* @return Evaluated attribute value
496
*/
497
public String evaluateAttribute(RangerAccessRequest request, RangerTagForEval tag);
498
499
/**
500
* Check if attribute evaluation is needed
501
* @return True if dynamic evaluation is required
502
*/
503
public boolean needsEvaluation();
504
}
505
506
/**
507
* Geographical location information
508
*/
509
public class GeoLocation {
510
/**
511
* Get country name
512
* @return Country name
513
*/
514
public String getCountry();
515
516
/**
517
* Get country code
518
* @return ISO country code
519
*/
520
public String getCountryCode();
521
522
/**
523
* Get state or province
524
* @return State/province name
525
*/
526
public String getState();
527
528
/**
529
* Get city name
530
* @return City name
531
*/
532
public String getCity();
533
534
/**
535
* Get latitude
536
* @return Latitude coordinate
537
*/
538
public Double getLatitude();
539
540
/**
541
* Get longitude
542
* @return Longitude coordinate
543
*/
544
public Double getLongitude();
545
}
546
```
547
548
**Usage Examples:**
549
550
```java
551
import org.apache.ranger.plugin.contextenricher.*;
552
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
553
554
// Configure and use tag enricher
555
public class TagEnrichmentExample {
556
public void setupTagEnricher() {
557
// Create tag enricher configuration
558
RangerContextEnricherDef enricherDef = new RangerContextEnricherDef();
559
enricherDef.setName("tag-enricher");
560
enricherDef.setEnricher("org.apache.ranger.plugin.contextenricher.RangerTagEnricher");
561
562
Map<String, String> options = new HashMap<>();
563
options.put("tag.source.type", "atlas");
564
options.put("tag.source.url", "http://atlas:21000");
565
options.put("tag.refresh.interval", "60000");
566
enricherDef.setEnricherOptions(options);
567
568
// Initialize tag enricher
569
RangerTagEnricher tagEnricher = new RangerTagEnricher();
570
tagEnricher.init(enricherDef, serviceDef, "MyApp");
571
572
// Use enricher with access request
573
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
574
request.setResource(resource);
575
request.setUser("alice");
576
request.setAccessType("read");
577
578
// Enrich request with tags
579
tagEnricher.enrich(request);
580
581
// Access enriched context
582
@SuppressWarnings("unchecked")
583
Set<RangerTagForEval> tags = (Set<RangerTagForEval>) request.getContext()
584
.get(RangerTagEnricher.TAG_ATTR_SET_KEY);
585
586
if (tags != null) {
587
for (RangerTagForEval tag : tags) {
588
System.out.println("Tag: " + tag.getType() +
589
" with attributes: " + tag.getAttributes());
590
}
591
}
592
}
593
}
594
595
// Configure and use user store enricher
596
public class UserStoreEnrichmentExample {
597
public void setupUserStoreEnricher() {
598
// Create user store enricher configuration
599
RangerContextEnricherDef enricherDef = new RangerContextEnricherDef();
600
enricherDef.setName("userstore-enricher");
601
enricherDef.setEnricher("org.apache.ranger.plugin.contextenricher.RangerUserStoreEnricher");
602
603
Map<String, String> options = new HashMap<>();
604
options.put("userstore.source.type", "ldap");
605
options.put("userstore.ldap.url", "ldap://ldap.company.com:389");
606
options.put("userstore.refresh.interval", "300000");
607
enricherDef.setEnricherOptions(options);
608
609
// Initialize user store enricher
610
RangerUserStoreEnricher userStoreEnricher = new RangerUserStoreEnricher();
611
userStoreEnricher.init(enricherDef, serviceDef, "MyApp");
612
613
// Use enricher with access request
614
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
615
request.setUser("alice");
616
request.setUserGroups(Set.of("analysts", "employees"));
617
618
// Enrich request with user attributes
619
userStoreEnricher.enrich(request);
620
621
// Access enriched user attributes
622
@SuppressWarnings("unchecked")
623
Map<String, String> userAttrs = (Map<String, String>) request.getContext()
624
.get(RangerUserStoreEnricher.USER_ATTRIBUTES_KEY);
625
626
if (userAttrs != null) {
627
System.out.println("User department: " + userAttrs.get("department"));
628
System.out.println("User location: " + userAttrs.get("location"));
629
System.out.println("User title: " + userAttrs.get("title"));
630
}
631
}
632
}
633
634
// Configure and use script enricher
635
public class ScriptEnrichmentExample {
636
public void setupScriptEnricher() {
637
// Create script enricher configuration
638
RangerContextEnricherDef enricherDef = new RangerContextEnricherDef();
639
enricherDef.setName("script-enricher");
640
enricherDef.setEnricher("org.apache.ranger.plugin.contextenricher.RangerScriptEnricher");
641
642
Map<String, String> options = new HashMap<>();
643
options.put(RangerScriptEnricher.SCRIPT_ENGINE_TYPE, "javascript");
644
options.put(RangerScriptEnricher.SCRIPT_CONTENT,
645
"var time = new Date().getHours();" +
646
"request.getContext().put('TIME_OF_DAY', " +
647
"time < 9 || time > 17 ? 'AFTER_HOURS' : 'BUSINESS_HOURS');" +
648
"request.getContext().put('ACCESS_TIMESTAMP', new Date().getTime());");
649
enricherDef.setEnricherOptions(options);
650
651
// Initialize script enricher
652
RangerScriptEnricher scriptEnricher = new RangerScriptEnricher();
653
scriptEnricher.init(enricherDef, serviceDef, "MyApp");
654
655
// Use enricher with access request
656
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
657
request.setUser("alice");
658
659
// Enrich request with script-generated context
660
scriptEnricher.enrich(request);
661
662
// Access enriched context
663
String timeOfDay = (String) request.getContext().get("TIME_OF_DAY");
664
Long timestamp = (Long) request.getContext().get("ACCESS_TIMESTAMP");
665
666
System.out.println("Access during: " + timeOfDay);
667
System.out.println("Access timestamp: " + new Date(timestamp));
668
}
669
}
670
671
// Configure and use geolocation enricher
672
public class GeolocationEnrichmentExample {
673
public void setupGeolocationEnricher() {
674
// Create geolocation enricher configuration
675
RangerContextEnricherDef enricherDef = new RangerContextEnricherDef();
676
enricherDef.setName("geo-enricher");
677
enricherDef.setEnricher("org.apache.ranger.plugin.contextenricher.RangerGeolocationEnricher");
678
679
Map<String, String> options = new HashMap<>();
680
options.put(RangerGeolocationEnricher.GEO_DB_PATH_CONFIG, "/opt/ranger/geo/GeoLite2-City.mmdb");
681
options.put(RangerGeolocationEnricher.GEO_ENABLED_CONFIG, "true");
682
enricherDef.setEnricherOptions(options);
683
684
// Initialize geolocation enricher
685
RangerGeolocationEnricher geoEnricher = new RangerGeolocationEnricher();
686
geoEnricher.init(enricherDef, serviceDef, "MyApp");
687
688
// Use enricher with access request
689
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
690
request.setUser("alice");
691
request.setClientIPAddress("192.168.1.100");
692
693
// Enrich request with geographical information
694
geoEnricher.enrich(request);
695
696
// Access enriched geographical context
697
String country = (String) request.getContext().get(RangerGeolocationEnricher.GEO_COUNTRY_KEY);
698
String state = (String) request.getContext().get(RangerGeolocationEnricher.GEO_STATE_KEY);
699
String city = (String) request.getContext().get(RangerGeolocationEnricher.GEO_CITY_KEY);
700
701
System.out.println("Access from: " + city + ", " + state + ", " + country);
702
}
703
}
704
```
705
706
## Context Enrichment Pipeline
707
708
Context enrichers are executed in a pipeline during policy evaluation:
709
710
1. **Initialization Phase**: All enrichers are initialized with their configuration
711
2. **Enrichment Phase**: Each enricher adds context to the access request in order
712
3. **Policy Evaluation**: Policies use enriched context for decision making
713
4. **Cleanup Phase**: Enrichers clean up resources if needed
714
715
## Enrichment Order and Dependencies
716
717
The order of context enrichment can be important:
718
719
- **Tag enrichers** typically run first to add resource tags
720
- **User store enrichers** add user/group attributes
721
- **Custom enrichers** (script, geolocation) run last
722
- **Dependencies** between enrichers can be configured in service definitions
723
724
## Performance Considerations
725
726
Context enrichment impacts policy evaluation performance:
727
728
- **Caching**: Enrichers should cache expensive lookups (user attributes, tags)
729
- **Lazy evaluation**: Only enrich context that policies actually use
730
- **Batch operations**: Use batch APIs when enriching multiple requests
731
- **Asynchronous updates**: Update enricher data sources asynchronously when possible
732
- **Timeout handling**: Implement timeouts for external data source lookups
733
734
## Configuration and Customization
735
736
Context enrichers are highly configurable:
737
738
- **Service definition configuration**: Defined in `RangerServiceDef.contextEnrichers`
739
- **Runtime options**: Passed via enricher options map
740
- **External data sources**: Support for LDAP, databases, REST APIs, files
741
- **Custom implementations**: Extend `RangerAbstractContextEnricher` for custom logic