Common library for Apache Ranger plugins providing shared functionality, models, and utilities for security policy enforcement across various big data components.
—
Flexible resource matching framework supporting various matching strategies including wildcards, regular expressions, and custom matchers. Resource matchers determine whether a policy's resource definition matches an access request's resource, enabling fine-grained control over which policies apply to specific resources.
Core interface for resource matching components that determine if a policy resource matches an access request resource.
/**
* Interface for resource matching components
*/
public interface RangerResourceMatcher {
/**
* Initialize the resource matcher with configuration
*/
public void init();
/**
* Check if the request resource matches the policy resource
* @param resource - Access request resource to match
* @param evalContext - Evaluation context for dynamic matching
* @return True if resource matches
*/
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check if the request resource completely matches the policy resource
* Complete match means the resource exactly matches without wildcards
* @param resource - Access request resource to match
* @param evalContext - Evaluation context for dynamic matching
* @return True if resource completely matches
*/
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check if this matcher needs dynamic evaluation
* Dynamic evaluation is required when matching depends on runtime context
* @return True if dynamic evaluation is needed
*/
public boolean getNeedsDynamicEval();
/**
* Get matching scope for optimization
* @return Matching scope information
*/
public MatchScope getMatchScope();
/**
* Set policy resource for matching
* @param policyResource - Policy resource definition
*/
public void setPolicyResource(RangerPolicyResource policyResource);
/**
* Get policy resource being matched
* @return Policy resource definition
*/
public RangerPolicyResource getPolicyResource();
}Abstract base class providing common functionality for resource matchers, including configuration management and utility methods.
/**
* Abstract base implementation for resource matchers
*/
public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher {
/**
* Resource definition from service definition
*/
protected RangerResourceDef resourceDef;
/**
* Policy resource being matched
*/
protected RangerPolicyResource policyResource;
/**
* Matcher options from configuration
*/
protected Map<String, String> options;
/**
* Service definition this matcher belongs to
*/
protected RangerServiceDef serviceDef;
/**
* Initialize the abstract resource matcher
* @param resourceDef - Resource definition
* @param policyResource - Policy resource
* @param serviceDef - Service definition
* @param options - Matcher options
*/
public void init(RangerResourceDef resourceDef, RangerPolicyResource policyResource,
RangerServiceDef serviceDef, Map<String, String> options);
/**
* Get matcher configuration options
* @return Map of configuration options
*/
public Map<String, String> getOptions();
/**
* Get a specific configuration option
* @param name - Option name
* @return Option value or null if not found
*/
public String getOption(String name);
/**
* Get a configuration option with default value
* @param name - Option name
* @param defaultValue - Default value if option not found
* @return Option value or default value
*/
public String getOption(String name, String defaultValue);
/**
* Get a boolean configuration option
* @param name - Option name
* @param defaultValue - Default value if option not found
* @return Boolean option value or default value
*/
public boolean getBooleanOption(String name, boolean defaultValue);
/**
* Check if policy resource values are empty
* @return True if no values defined
*/
public boolean isMatchAny();
/**
* Get policy resource values
* @return List of resource values from policy
*/
public List<String> getPolicyValues();
/**
* Check if policy resource excludes matches
* @return True if exclude flag is set
*/
public boolean getIsExcludes();
/**
* Get the resource name being matched
* @return Resource name
*/
public String getResourceName();
/**
* Default implementation for dynamic evaluation check
* @return False by default
*/
@Override
public boolean getNeedsDynamicEval();
/**
* Default implementation for match scope
* @return Default match scope
*/
@Override
public MatchScope getMatchScope();
/**
* Utility method to normalize resource values
* @param values - Values to normalize
* @return Normalized values
*/
protected List<String> normalizeValues(List<String> values);
/**
* Check if a value matches any of the policy values
* @param value - Value to check
* @param policyValues - Policy values to match against
* @param evalContext - Evaluation context
* @return True if value matches
*/
protected boolean isValueMatch(String value, List<String> policyValues, Map<String, Object> evalContext);
}Default resource matcher supporting wildcard matching with support for * and ? wildcards.
/**
* Default resource matcher with wildcard support
*/
public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher {
/**
* Wildcard character for multiple characters
*/
public static final char WILDCARD_ASTERISK = '*';
/**
* Wildcard character for single character
*/
public static final char WILDCARD_QUESTION_MARK = '?';
/**
* Initialize the default resource matcher
*/
@Override
public void init();
/**
* Check if resource matches using wildcard pattern matching
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if resource matches
*/
@Override
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check for complete match (no wildcards)
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if resource completely matches
*/
@Override
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check if a string matches a wildcard pattern
* @param str - String to check
* @param pattern - Wildcard pattern
* @return True if string matches pattern
*/
public boolean wildcardMatch(String str, String pattern);
/**
* Check if a string matches a wildcard pattern with case sensitivity option
* @param str - String to check
* @param pattern - Wildcard pattern
* @param caseSensitive - True for case-sensitive matching
* @return True if string matches pattern
*/
public boolean wildcardMatch(String str, String pattern, boolean caseSensitive);
/**
* Compile wildcard pattern for efficient matching
* @param pattern - Wildcard pattern to compile
* @return Compiled pattern matcher
*/
public WildcardMatcher compilePattern(String pattern);
/**
* Check if pattern contains wildcards
* @param pattern - Pattern to check
* @return True if pattern has wildcards
*/
public boolean hasWildcards(String pattern);
}Specialized resource matcher for hierarchical path resources with support for path-specific matching rules.
/**
* Resource matcher for hierarchical path resources
*/
public class RangerPathResourceMatcher extends RangerAbstractResourceMatcher {
/**
* Path separator character
*/
public static final char PATH_SEPARATOR = '/';
/**
* Configuration option for path separator
*/
public static final String OPTION_PATH_SEPARATOR = "path.separator";
/**
* Configuration option for case sensitivity
*/
public static final String OPTION_CASE_SENSITIVE = "case.sensitive";
/**
* Initialize the path resource matcher
*/
@Override
public void init();
/**
* Check if path matches using path-aware matching
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if path matches
*/
@Override
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check for complete path match
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if path completely matches
*/
@Override
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check if request path matches policy path
* @param requestPath - Path from access request
* @param policyPath - Path pattern from policy
* @return True if paths match
*/
public boolean isPathMatch(String requestPath, String policyPath);
/**
* Check if request path is a child of policy path
* @param requestPath - Path from access request
* @param policyPath - Path pattern from policy
* @return True if request path is under policy path
*/
public boolean isChildPath(String requestPath, String policyPath);
/**
* Normalize path by removing extra separators and handling relative paths
* @param path - Path to normalize
* @return Normalized path
*/
public String normalizePath(String path);
/**
* Split path into components
* @param path - Path to split
* @return Array of path components
*/
public String[] getPathComponents(String path);
/**
* Check if path is recursive match
* @param requestPath - Path from access request
* @param policyPath - Path pattern from policy
* @return True if recursive match applies
*/
public boolean isRecursiveMatch(String requestPath, String policyPath);
/**
* Get path separator character
* @return Path separator
*/
public char getPathSeparator();
}Resource matcher supporting regular expression pattern matching for complex resource matching requirements.
/**
* Resource matcher with regular expression support
*/
public class RangerRegexResourceMatcher extends RangerAbstractResourceMatcher {
/**
* Configuration option for regex flags
*/
public static final String OPTION_REGEX_FLAGS = "regex.flags";
/**
* Configuration option for case insensitive matching
*/
public static final String OPTION_CASE_INSENSITIVE = "case.insensitive";
/**
* Initialize the regex resource matcher
*/
@Override
public void init();
/**
* Check if resource matches using regular expression matching
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if resource matches
*/
@Override
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Check for complete regex match
* @param resource - Access request resource
* @param evalContext - Evaluation context
* @return True if resource completely matches
*/
@Override
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
/**
* Compile regular expression pattern
* @param pattern - Regex pattern to compile
* @return Compiled pattern
*/
public Pattern compileRegex(String pattern);
/**
* Check if string matches regex pattern
* @param str - String to check
* @param pattern - Compiled regex pattern
* @return True if string matches
*/
public boolean regexMatch(String str, Pattern pattern);
/**
* Get regex flags for compilation
* @return Regex flags
*/
public int getRegexFlags();
}Supporting classes and enumerations for resource matching functionality.
/**
* Enumeration of matching scope types for optimization
*/
public enum MatchScope {
/**
* Self-only matching - matches only the exact resource
*/
SELF,
/**
* Self and child matching - matches resource and its children
*/
SELF_AND_CHILD,
/**
* Self and ancestor matching - matches resource and its ancestors
*/
SELF_AND_ANCESTOR,
/**
* Self, ancestor, and child matching - matches resource, ancestors, and children
*/
SELF_ANCESTOR_AND_CHILD
}
/**
* Compiled wildcard pattern matcher for efficient matching
*/
public class WildcardMatcher {
/**
* Check if string matches this compiled pattern
* @param str - String to match
* @return True if string matches
*/
public boolean match(String str);
/**
* Check if pattern has wildcards
* @return True if pattern contains wildcards
*/
public boolean hasWildcard();
/**
* Get the original pattern
* @return Original pattern string
*/
public String getPattern();
}
/**
* Path matching utilities
*/
public class PathUtils {
/**
* Normalize path separators and handle relative paths
* @param path - Path to normalize
* @param separator - Path separator character
* @return Normalized path
*/
public static String normalizePath(String path, char separator);
/**
* Check if path is absolute
* @param path - Path to check
* @param separator - Path separator character
* @return True if path is absolute
*/
public static boolean isAbsolute(String path, char separator);
/**
* Get parent path
* @param path - Child path
* @param separator - Path separator character
* @return Parent path or null if no parent
*/
public static String getParent(String path, char separator);
/**
* Join path components
* @param components - Path components to join
* @param separator - Path separator character
* @return Joined path
*/
public static String joinPaths(String[] components, char separator);
}
/**
* Resource matching context for optimization
*/
public class ResourceMatchingContext {
/**
* Get cached matcher for resource
* @param resourceName - Name of resource
* @return Cached matcher or null
*/
public RangerResourceMatcher getCachedMatcher(String resourceName);
/**
* Cache matcher for resource
* @param resourceName - Name of resource
* @param matcher - Matcher to cache
*/
public void cacheMatcher(String resourceName, RangerResourceMatcher matcher);
/**
* Clear matcher cache
*/
public void clearCache();
}Usage Examples:
import org.apache.ranger.plugin.resourcematcher.*;
import org.apache.ranger.plugin.model.*;
import org.apache.ranger.plugin.policyengine.*;
// Using default wildcard matcher
public class WildcardMatchingExample {
public void setupWildcardMatcher() {
// Create resource definition
RangerResourceDef resourceDef = new RangerResourceDef();
resourceDef.setName("path");
resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher");
// Create policy resource
RangerPolicyResource policyResource = new RangerPolicyResource();
policyResource.setValues(Arrays.asList("/data/*", "/logs/app*.log"));
policyResource.setIsExcludes(false);
policyResource.setIsRecursive(true);
// Initialize matcher
RangerDefaultResourceMatcher matcher = new RangerDefaultResourceMatcher();
matcher.init(resourceDef, policyResource, serviceDef, new HashMap<>());
// Create test resource
RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();
testResource.setValue("path", "/data/users/alice.txt");
// Test matching
boolean matches = matcher.isMatch(testResource, null);
System.out.println("Resource matches: " + matches); // true
// Test different paths
testResource.setValue("path", "/logs/app-2024.log");
matches = matcher.isMatch(testResource, null);
System.out.println("Log file matches: " + matches); // true
testResource.setValue("path", "/config/settings.xml");
matches = matcher.isMatch(testResource, null);
System.out.println("Config file matches: " + matches); // false
}
}
// Using path matcher for hierarchical resources
public class PathMatchingExample {
public void setupPathMatcher() {
// Create resource definition for paths
RangerResourceDef resourceDef = new RangerResourceDef();
resourceDef.setName("path");
resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher");
Map<String, String> matcherOptions = new HashMap<>();
matcherOptions.put(RangerPathResourceMatcher.OPTION_PATH_SEPARATOR, "/");
matcherOptions.put(RangerPathResourceMatcher.OPTION_CASE_SENSITIVE, "true");
// Create policy resource for recursive matching
RangerPolicyResource policyResource = new RangerPolicyResource();
policyResource.setValues(Arrays.asList("/user/data"));
policyResource.setIsRecursive(true);
policyResource.setIsExcludes(false);
// Initialize path matcher
RangerPathResourceMatcher matcher = new RangerPathResourceMatcher();
matcher.init(resourceDef, policyResource, serviceDef, matcherOptions);
// Test various path scenarios
RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();
// Direct match
testResource.setValue("path", "/user/data");
boolean matches = matcher.isMatch(testResource, null);
System.out.println("Direct path matches: " + matches); // true
// Child path (recursive match)
testResource.setValue("path", "/user/data/files/document.txt");
matches = matcher.isMatch(testResource, null);
System.out.println("Child path matches: " + matches); // true
// Parent path
testResource.setValue("path", "/user");
matches = matcher.isMatch(testResource, null);
System.out.println("Parent path matches: " + matches); // false
// Sibling path
testResource.setValue("path", "/user/config");
matches = matcher.isMatch(testResource, null);
System.out.println("Sibling path matches: " + matches); // false
}
}
// Using regex matcher for complex patterns
public class RegexMatchingExample {
public void setupRegexMatcher() {
// Create resource definition
RangerResourceDef resourceDef = new RangerResourceDef();
resourceDef.setName("table");
resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerRegexResourceMatcher");
Map<String, String> matcherOptions = new HashMap<>();
matcherOptions.put(RangerRegexResourceMatcher.OPTION_CASE_INSENSITIVE, "true");
// Create policy resource with regex patterns
RangerPolicyResource policyResource = new RangerPolicyResource();
policyResource.setValues(Arrays.asList(
"sales_[0-9]{4}_[0-9]{2}", // sales_YYYY_MM pattern
"temp_.*", // temporary tables
"user_[a-zA-Z]+_data" // user data tables
));
policyResource.setIsExcludes(false);
// Initialize regex matcher
RangerRegexResourceMatcher matcher = new RangerRegexResourceMatcher();
matcher.init(resourceDef, policyResource, serviceDef, matcherOptions);
// Test various table names
RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();
// Sales table with year/month pattern
testResource.setValue("table", "sales_2024_03");
boolean matches = matcher.isMatch(testResource, null);
System.out.println("Sales table matches: " + matches); // true
// Temporary table
testResource.setValue("table", "TEMP_PROCESSING_DATA");
matches = matcher.isMatch(testResource, null);
System.out.println("Temp table matches: " + matches); // true (case insensitive)
// User data table
testResource.setValue("table", "user_alice_data");
matches = matcher.isMatch(testResource, null);
System.out.println("User table matches: " + matches); // true
// Non-matching table
testResource.setValue("table", "production_main");
matches = matcher.isMatch(testResource, null);
System.out.println("Production table matches: " + matches); // false
}
}
// Custom resource matcher implementation
public class CustomResourceMatcher extends RangerAbstractResourceMatcher {
private static final String OPTION_CUSTOM_LOGIC = "custom.logic";
@Override
public void init() {
super.init();
// Custom initialization logic
String customLogic = getOption(OPTION_CUSTOM_LOGIC, "default");
System.out.println("Initializing custom matcher with logic: " + customLogic);
}
@Override
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
// Get the resource value
String resourceValue = resource.getValue(getResourceName());
if (resourceValue == null) {
return false;
}
// Custom matching logic - example: time-based matching
List<String> policyValues = getPolicyValues();
for (String policyValue : policyValues) {
if (customMatch(resourceValue, policyValue, evalContext)) {
return !getIsExcludes(); // Apply exclude logic
}
}
return getIsExcludes(); // Return opposite if excludes
}
@Override
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
// For this custom matcher, complete match is the same as regular match
return isMatch(resource, evalContext);
}
private boolean customMatch(String resourceValue, String policyValue, Map<String, Object> evalContext) {
// Example: Match based on current time and resource pattern
// Policy value format: "resource_pattern:time_range"
String[] parts = policyValue.split(":");
if (parts.length != 2) {
return resourceValue.equals(policyValue); // Fallback to exact match
}
String pattern = parts[0];
String timeRange = parts[1]; // Format: "09:00-17:00"
// Check pattern match first
if (!wildcardMatch(resourceValue, pattern)) {
return false;
}
// Check time range
return isWithinTimeRange(timeRange);
}
private boolean wildcardMatch(String str, String pattern) {
// Simple wildcard matching implementation
return str.matches(pattern.replace("*", ".*").replace("?", "."));
}
private boolean isWithinTimeRange(String timeRange) {
try {
String[] times = timeRange.split("-");
if (times.length != 2) {
return true; // Invalid format, allow access
}
int currentHour = java.time.LocalTime.now().getHour();
int startHour = Integer.parseInt(times[0].split(":")[0]);
int endHour = Integer.parseInt(times[1].split(":")[0]);
return currentHour >= startHour && currentHour <= endHour;
} catch (Exception e) {
return true; // Error in parsing, allow access
}
}
}Different matching strategies are available depending on resource types:
* (multiple characters), ? (single character)RangerDefaultResourceMatcherRangerPathResourceMatcherRangerRegexResourceMatcherResource matching can impact policy evaluation performance:
MatchScope to optimize policy selectionResource matchers support extensive configuration:
RangerResourceDef resourceDef = new RangerResourceDef();
resourceDef.setName("path");
resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher");
Map<String, String> matcherOptions = new HashMap<>();
matcherOptions.put("path.separator", "/");
matcherOptions.put("case.sensitive", "true");
matcherOptions.put("normalize.paths", "true");
resourceDef.setMatcherOptions(matcherOptions);Implement RangerResourceMatcher or extend RangerAbstractResourceMatcher for custom matching logic tailored to specific resource types and business requirements.
Install with Tessl CLI
npx tessl i tessl/maven-org-apache-ranger--ranger-plugins-common