or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-client.mdauthentication-security.mdcontext-enrichment.mdindex.mdplugin-services.mdpolicy-engine.mdpolicy-models.mdresource-matching.md

resource-matching.mddocs/

0

# Resource Matching

1

2

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.

3

4

## Capabilities

5

6

### RangerResourceMatcher

7

8

Core interface for resource matching components that determine if a policy resource matches an access request resource.

9

10

```java { .api }

11

/**

12

* Interface for resource matching components

13

*/

14

public interface RangerResourceMatcher {

15

/**

16

* Initialize the resource matcher with configuration

17

*/

18

public void init();

19

20

/**

21

* Check if the request resource matches the policy resource

22

* @param resource - Access request resource to match

23

* @param evalContext - Evaluation context for dynamic matching

24

* @return True if resource matches

25

*/

26

public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);

27

28

/**

29

* Check if the request resource completely matches the policy resource

30

* Complete match means the resource exactly matches without wildcards

31

* @param resource - Access request resource to match

32

* @param evalContext - Evaluation context for dynamic matching

33

* @return True if resource completely matches

34

*/

35

public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);

36

37

/**

38

* Check if this matcher needs dynamic evaluation

39

* Dynamic evaluation is required when matching depends on runtime context

40

* @return True if dynamic evaluation is needed

41

*/

42

public boolean getNeedsDynamicEval();

43

44

/**

45

* Get matching scope for optimization

46

* @return Matching scope information

47

*/

48

public MatchScope getMatchScope();

49

50

/**

51

* Set policy resource for matching

52

* @param policyResource - Policy resource definition

53

*/

54

public void setPolicyResource(RangerPolicyResource policyResource);

55

56

/**

57

* Get policy resource being matched

58

* @return Policy resource definition

59

*/

60

public RangerPolicyResource getPolicyResource();

61

}

62

```

63

64

### RangerAbstractResourceMatcher

65

66

Abstract base class providing common functionality for resource matchers, including configuration management and utility methods.

67

68

```java { .api }

69

/**

70

* Abstract base implementation for resource matchers

71

*/

72

public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher {

73

/**

74

* Resource definition from service definition

75

*/

76

protected RangerResourceDef resourceDef;

77

78

/**

79

* Policy resource being matched

80

*/

81

protected RangerPolicyResource policyResource;

82

83

/**

84

* Matcher options from configuration

85

*/

86

protected Map<String, String> options;

87

88

/**

89

* Service definition this matcher belongs to

90

*/

91

protected RangerServiceDef serviceDef;

92

93

/**

94

* Initialize the abstract resource matcher

95

* @param resourceDef - Resource definition

96

* @param policyResource - Policy resource

97

* @param serviceDef - Service definition

98

* @param options - Matcher options

99

*/

100

public void init(RangerResourceDef resourceDef, RangerPolicyResource policyResource,

101

RangerServiceDef serviceDef, Map<String, String> options);

102

103

/**

104

* Get matcher configuration options

105

* @return Map of configuration options

106

*/

107

public Map<String, String> getOptions();

108

109

/**

110

* Get a specific configuration option

111

* @param name - Option name

112

* @return Option value or null if not found

113

*/

114

public String getOption(String name);

115

116

/**

117

* Get a configuration option with default value

118

* @param name - Option name

119

* @param defaultValue - Default value if option not found

120

* @return Option value or default value

121

*/

122

public String getOption(String name, String defaultValue);

123

124

/**

125

* Get a boolean configuration option

126

* @param name - Option name

127

* @param defaultValue - Default value if option not found

128

* @return Boolean option value or default value

129

*/

130

public boolean getBooleanOption(String name, boolean defaultValue);

131

132

/**

133

* Check if policy resource values are empty

134

* @return True if no values defined

135

*/

136

public boolean isMatchAny();

137

138

/**

139

* Get policy resource values

140

* @return List of resource values from policy

141

*/

142

public List<String> getPolicyValues();

143

144

/**

145

* Check if policy resource excludes matches

146

* @return True if exclude flag is set

147

*/

148

public boolean getIsExcludes();

149

150

/**

151

* Get the resource name being matched

152

* @return Resource name

153

*/

154

public String getResourceName();

155

156

/**

157

* Default implementation for dynamic evaluation check

158

* @return False by default

159

*/

160

@Override

161

public boolean getNeedsDynamicEval();

162

163

/**

164

* Default implementation for match scope

165

* @return Default match scope

166

*/

167

@Override

168

public MatchScope getMatchScope();

169

170

/**

171

* Utility method to normalize resource values

172

* @param values - Values to normalize

173

* @return Normalized values

174

*/

175

protected List<String> normalizeValues(List<String> values);

176

177

/**

178

* Check if a value matches any of the policy values

179

* @param value - Value to check

180

* @param policyValues - Policy values to match against

181

* @param evalContext - Evaluation context

182

* @return True if value matches

183

*/

184

protected boolean isValueMatch(String value, List<String> policyValues, Map<String, Object> evalContext);

185

}

186

```

187

188

### RangerDefaultResourceMatcher

189

190

Default resource matcher supporting wildcard matching with support for `*` and `?` wildcards.

191

192

```java { .api }

193

/**

194

* Default resource matcher with wildcard support

195

*/

196

public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher {

197

/**

198

* Wildcard character for multiple characters

199

*/

200

public static final char WILDCARD_ASTERISK = '*';

201

202

/**

203

* Wildcard character for single character

204

*/

205

public static final char WILDCARD_QUESTION_MARK = '?';

206

207

/**

208

* Initialize the default resource matcher

209

*/

210

@Override

211

public void init();

212

213

/**

214

* Check if resource matches using wildcard pattern matching

215

* @param resource - Access request resource

216

* @param evalContext - Evaluation context

217

* @return True if resource matches

218

*/

219

@Override

220

public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);

221

222

/**

223

* Check for complete match (no wildcards)

224

* @param resource - Access request resource

225

* @param evalContext - Evaluation context

226

* @return True if resource completely matches

227

*/

228

@Override

229

public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);

230

231

/**

232

* Check if a string matches a wildcard pattern

233

* @param str - String to check

234

* @param pattern - Wildcard pattern

235

* @return True if string matches pattern

236

*/

237

public boolean wildcardMatch(String str, String pattern);

238

239

/**

240

* Check if a string matches a wildcard pattern with case sensitivity option

241

* @param str - String to check

242

* @param pattern - Wildcard pattern

243

* @param caseSensitive - True for case-sensitive matching

244

* @return True if string matches pattern

245

*/

246

public boolean wildcardMatch(String str, String pattern, boolean caseSensitive);

247

248

/**

249

* Compile wildcard pattern for efficient matching

250

* @param pattern - Wildcard pattern to compile

251

* @return Compiled pattern matcher

252

*/

253

public WildcardMatcher compilePattern(String pattern);

254

255

/**

256

* Check if pattern contains wildcards

257

* @param pattern - Pattern to check

258

* @return True if pattern has wildcards

259

*/

260

public boolean hasWildcards(String pattern);

261

}

262

```

263

264

### RangerPathResourceMatcher

265

266

Specialized resource matcher for hierarchical path resources with support for path-specific matching rules.

267

268

```java { .api }

269

/**

270

* Resource matcher for hierarchical path resources

271

*/

272

public class RangerPathResourceMatcher extends RangerAbstractResourceMatcher {

273

/**

274

* Path separator character

275

*/

276

public static final char PATH_SEPARATOR = '/';

277

278

/**

279

* Configuration option for path separator

280

*/

281

public static final String OPTION_PATH_SEPARATOR = "path.separator";

282

283

/**

284

* Configuration option for case sensitivity

285

*/

286

public static final String OPTION_CASE_SENSITIVE = "case.sensitive";

287

288

/**

289

* Initialize the path resource matcher

290

*/

291

@Override

292

public void init();

293

294

/**

295

* Check if path matches using path-aware matching

296

* @param resource - Access request resource

297

* @param evalContext - Evaluation context

298

* @return True if path matches

299

*/

300

@Override

301

public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);

302

303

/**

304

* Check for complete path match

305

* @param resource - Access request resource

306

* @param evalContext - Evaluation context

307

* @return True if path completely matches

308

*/

309

@Override

310

public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);

311

312

/**

313

* Check if request path matches policy path

314

* @param requestPath - Path from access request

315

* @param policyPath - Path pattern from policy

316

* @return True if paths match

317

*/

318

public boolean isPathMatch(String requestPath, String policyPath);

319

320

/**

321

* Check if request path is a child of policy path

322

* @param requestPath - Path from access request

323

* @param policyPath - Path pattern from policy

324

* @return True if request path is under policy path

325

*/

326

public boolean isChildPath(String requestPath, String policyPath);

327

328

/**

329

* Normalize path by removing extra separators and handling relative paths

330

* @param path - Path to normalize

331

* @return Normalized path

332

*/

333

public String normalizePath(String path);

334

335

/**

336

* Split path into components

337

* @param path - Path to split

338

* @return Array of path components

339

*/

340

public String[] getPathComponents(String path);

341

342

/**

343

* Check if path is recursive match

344

* @param requestPath - Path from access request

345

* @param policyPath - Path pattern from policy

346

* @return True if recursive match applies

347

*/

348

public boolean isRecursiveMatch(String requestPath, String policyPath);

349

350

/**

351

* Get path separator character

352

* @return Path separator

353

*/

354

public char getPathSeparator();

355

}

356

```

357

358

### RangerRegexResourceMatcher

359

360

Resource matcher supporting regular expression pattern matching for complex resource matching requirements.

361

362

```java { .api }

363

/**

364

* Resource matcher with regular expression support

365

*/

366

public class RangerRegexResourceMatcher extends RangerAbstractResourceMatcher {

367

/**

368

* Configuration option for regex flags

369

*/

370

public static final String OPTION_REGEX_FLAGS = "regex.flags";

371

372

/**

373

* Configuration option for case insensitive matching

374

*/

375

public static final String OPTION_CASE_INSENSITIVE = "case.insensitive";

376

377

/**

378

* Initialize the regex resource matcher

379

*/

380

@Override

381

public void init();

382

383

/**

384

* Check if resource matches using regular expression matching

385

* @param resource - Access request resource

386

* @param evalContext - Evaluation context

387

* @return True if resource matches

388

*/

389

@Override

390

public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);

391

392

/**

393

* Check for complete regex match

394

* @param resource - Access request resource

395

* @param evalContext - Evaluation context

396

* @return True if resource completely matches

397

*/

398

@Override

399

public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);

400

401

/**

402

* Compile regular expression pattern

403

* @param pattern - Regex pattern to compile

404

* @return Compiled pattern

405

*/

406

public Pattern compileRegex(String pattern);

407

408

/**

409

* Check if string matches regex pattern

410

* @param str - String to check

411

* @param pattern - Compiled regex pattern

412

* @return True if string matches

413

*/

414

public boolean regexMatch(String str, Pattern pattern);

415

416

/**

417

* Get regex flags for compilation

418

* @return Regex flags

419

*/

420

public int getRegexFlags();

421

}

422

```

423

424

### Resource Matching Helper Classes

425

426

Supporting classes and enumerations for resource matching functionality.

427

428

```java { .api }

429

/**

430

* Enumeration of matching scope types for optimization

431

*/

432

public enum MatchScope {

433

/**

434

* Self-only matching - matches only the exact resource

435

*/

436

SELF,

437

438

/**

439

* Self and child matching - matches resource and its children

440

*/

441

SELF_AND_CHILD,

442

443

/**

444

* Self and ancestor matching - matches resource and its ancestors

445

*/

446

SELF_AND_ANCESTOR,

447

448

/**

449

* Self, ancestor, and child matching - matches resource, ancestors, and children

450

*/

451

SELF_ANCESTOR_AND_CHILD

452

}

453

454

/**

455

* Compiled wildcard pattern matcher for efficient matching

456

*/

457

public class WildcardMatcher {

458

/**

459

* Check if string matches this compiled pattern

460

* @param str - String to match

461

* @return True if string matches

462

*/

463

public boolean match(String str);

464

465

/**

466

* Check if pattern has wildcards

467

* @return True if pattern contains wildcards

468

*/

469

public boolean hasWildcard();

470

471

/**

472

* Get the original pattern

473

* @return Original pattern string

474

*/

475

public String getPattern();

476

}

477

478

/**

479

* Path matching utilities

480

*/

481

public class PathUtils {

482

/**

483

* Normalize path separators and handle relative paths

484

* @param path - Path to normalize

485

* @param separator - Path separator character

486

* @return Normalized path

487

*/

488

public static String normalizePath(String path, char separator);

489

490

/**

491

* Check if path is absolute

492

* @param path - Path to check

493

* @param separator - Path separator character

494

* @return True if path is absolute

495

*/

496

public static boolean isAbsolute(String path, char separator);

497

498

/**

499

* Get parent path

500

* @param path - Child path

501

* @param separator - Path separator character

502

* @return Parent path or null if no parent

503

*/

504

public static String getParent(String path, char separator);

505

506

/**

507

* Join path components

508

* @param components - Path components to join

509

* @param separator - Path separator character

510

* @return Joined path

511

*/

512

public static String joinPaths(String[] components, char separator);

513

}

514

515

/**

516

* Resource matching context for optimization

517

*/

518

public class ResourceMatchingContext {

519

/**

520

* Get cached matcher for resource

521

* @param resourceName - Name of resource

522

* @return Cached matcher or null

523

*/

524

public RangerResourceMatcher getCachedMatcher(String resourceName);

525

526

/**

527

* Cache matcher for resource

528

* @param resourceName - Name of resource

529

* @param matcher - Matcher to cache

530

*/

531

public void cacheMatcher(String resourceName, RangerResourceMatcher matcher);

532

533

/**

534

* Clear matcher cache

535

*/

536

public void clearCache();

537

}

538

```

539

540

**Usage Examples:**

541

542

```java

543

import org.apache.ranger.plugin.resourcematcher.*;

544

import org.apache.ranger.plugin.model.*;

545

import org.apache.ranger.plugin.policyengine.*;

546

547

// Using default wildcard matcher

548

public class WildcardMatchingExample {

549

public void setupWildcardMatcher() {

550

// Create resource definition

551

RangerResourceDef resourceDef = new RangerResourceDef();

552

resourceDef.setName("path");

553

resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher");

554

555

// Create policy resource

556

RangerPolicyResource policyResource = new RangerPolicyResource();

557

policyResource.setValues(Arrays.asList("/data/*", "/logs/app*.log"));

558

policyResource.setIsExcludes(false);

559

policyResource.setIsRecursive(true);

560

561

// Initialize matcher

562

RangerDefaultResourceMatcher matcher = new RangerDefaultResourceMatcher();

563

matcher.init(resourceDef, policyResource, serviceDef, new HashMap<>());

564

565

// Create test resource

566

RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();

567

testResource.setValue("path", "/data/users/alice.txt");

568

569

// Test matching

570

boolean matches = matcher.isMatch(testResource, null);

571

System.out.println("Resource matches: " + matches); // true

572

573

// Test different paths

574

testResource.setValue("path", "/logs/app-2024.log");

575

matches = matcher.isMatch(testResource, null);

576

System.out.println("Log file matches: " + matches); // true

577

578

testResource.setValue("path", "/config/settings.xml");

579

matches = matcher.isMatch(testResource, null);

580

System.out.println("Config file matches: " + matches); // false

581

}

582

}

583

584

// Using path matcher for hierarchical resources

585

public class PathMatchingExample {

586

public void setupPathMatcher() {

587

// Create resource definition for paths

588

RangerResourceDef resourceDef = new RangerResourceDef();

589

resourceDef.setName("path");

590

resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher");

591

592

Map<String, String> matcherOptions = new HashMap<>();

593

matcherOptions.put(RangerPathResourceMatcher.OPTION_PATH_SEPARATOR, "/");

594

matcherOptions.put(RangerPathResourceMatcher.OPTION_CASE_SENSITIVE, "true");

595

596

// Create policy resource for recursive matching

597

RangerPolicyResource policyResource = new RangerPolicyResource();

598

policyResource.setValues(Arrays.asList("/user/data"));

599

policyResource.setIsRecursive(true);

600

policyResource.setIsExcludes(false);

601

602

// Initialize path matcher

603

RangerPathResourceMatcher matcher = new RangerPathResourceMatcher();

604

matcher.init(resourceDef, policyResource, serviceDef, matcherOptions);

605

606

// Test various path scenarios

607

RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();

608

609

// Direct match

610

testResource.setValue("path", "/user/data");

611

boolean matches = matcher.isMatch(testResource, null);

612

System.out.println("Direct path matches: " + matches); // true

613

614

// Child path (recursive match)

615

testResource.setValue("path", "/user/data/files/document.txt");

616

matches = matcher.isMatch(testResource, null);

617

System.out.println("Child path matches: " + matches); // true

618

619

// Parent path

620

testResource.setValue("path", "/user");

621

matches = matcher.isMatch(testResource, null);

622

System.out.println("Parent path matches: " + matches); // false

623

624

// Sibling path

625

testResource.setValue("path", "/user/config");

626

matches = matcher.isMatch(testResource, null);

627

System.out.println("Sibling path matches: " + matches); // false

628

}

629

}

630

631

// Using regex matcher for complex patterns

632

public class RegexMatchingExample {

633

public void setupRegexMatcher() {

634

// Create resource definition

635

RangerResourceDef resourceDef = new RangerResourceDef();

636

resourceDef.setName("table");

637

resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerRegexResourceMatcher");

638

639

Map<String, String> matcherOptions = new HashMap<>();

640

matcherOptions.put(RangerRegexResourceMatcher.OPTION_CASE_INSENSITIVE, "true");

641

642

// Create policy resource with regex patterns

643

RangerPolicyResource policyResource = new RangerPolicyResource();

644

policyResource.setValues(Arrays.asList(

645

"sales_[0-9]{4}_[0-9]{2}", // sales_YYYY_MM pattern

646

"temp_.*", // temporary tables

647

"user_[a-zA-Z]+_data" // user data tables

648

));

649

policyResource.setIsExcludes(false);

650

651

// Initialize regex matcher

652

RangerRegexResourceMatcher matcher = new RangerRegexResourceMatcher();

653

matcher.init(resourceDef, policyResource, serviceDef, matcherOptions);

654

655

// Test various table names

656

RangerAccessResourceImpl testResource = new RangerAccessResourceImpl();

657

658

// Sales table with year/month pattern

659

testResource.setValue("table", "sales_2024_03");

660

boolean matches = matcher.isMatch(testResource, null);

661

System.out.println("Sales table matches: " + matches); // true

662

663

// Temporary table

664

testResource.setValue("table", "TEMP_PROCESSING_DATA");

665

matches = matcher.isMatch(testResource, null);

666

System.out.println("Temp table matches: " + matches); // true (case insensitive)

667

668

// User data table

669

testResource.setValue("table", "user_alice_data");

670

matches = matcher.isMatch(testResource, null);

671

System.out.println("User table matches: " + matches); // true

672

673

// Non-matching table

674

testResource.setValue("table", "production_main");

675

matches = matcher.isMatch(testResource, null);

676

System.out.println("Production table matches: " + matches); // false

677

}

678

}

679

680

// Custom resource matcher implementation

681

public class CustomResourceMatcher extends RangerAbstractResourceMatcher {

682

private static final String OPTION_CUSTOM_LOGIC = "custom.logic";

683

684

@Override

685

public void init() {

686

super.init();

687

// Custom initialization logic

688

String customLogic = getOption(OPTION_CUSTOM_LOGIC, "default");

689

System.out.println("Initializing custom matcher with logic: " + customLogic);

690

}

691

692

@Override

693

public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {

694

// Get the resource value

695

String resourceValue = resource.getValue(getResourceName());

696

if (resourceValue == null) {

697

return false;

698

}

699

700

// Custom matching logic - example: time-based matching

701

List<String> policyValues = getPolicyValues();

702

for (String policyValue : policyValues) {

703

if (customMatch(resourceValue, policyValue, evalContext)) {

704

return !getIsExcludes(); // Apply exclude logic

705

}

706

}

707

708

return getIsExcludes(); // Return opposite if excludes

709

}

710

711

@Override

712

public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext) {

713

// For this custom matcher, complete match is the same as regular match

714

return isMatch(resource, evalContext);

715

}

716

717

private boolean customMatch(String resourceValue, String policyValue, Map<String, Object> evalContext) {

718

// Example: Match based on current time and resource pattern

719

// Policy value format: "resource_pattern:time_range"

720

String[] parts = policyValue.split(":");

721

if (parts.length != 2) {

722

return resourceValue.equals(policyValue); // Fallback to exact match

723

}

724

725

String pattern = parts[0];

726

String timeRange = parts[1]; // Format: "09:00-17:00"

727

728

// Check pattern match first

729

if (!wildcardMatch(resourceValue, pattern)) {

730

return false;

731

}

732

733

// Check time range

734

return isWithinTimeRange(timeRange);

735

}

736

737

private boolean wildcardMatch(String str, String pattern) {

738

// Simple wildcard matching implementation

739

return str.matches(pattern.replace("*", ".*").replace("?", "."));

740

}

741

742

private boolean isWithinTimeRange(String timeRange) {

743

try {

744

String[] times = timeRange.split("-");

745

if (times.length != 2) {

746

return true; // Invalid format, allow access

747

}

748

749

int currentHour = java.time.LocalTime.now().getHour();

750

int startHour = Integer.parseInt(times[0].split(":")[0]);

751

int endHour = Integer.parseInt(times[1].split(":")[0]);

752

753

return currentHour >= startHour && currentHour <= endHour;

754

} catch (Exception e) {

755

return true; // Error in parsing, allow access

756

}

757

}

758

}

759

```

760

761

## Resource Matching Strategies

762

763

Different matching strategies are available depending on resource types:

764

765

### Exact Matching

766

- **Use case**: Database names, user names, fixed identifiers

767

- **Implementation**: Direct string comparison

768

- **Performance**: Fastest matching strategy

769

770

### Wildcard Matching

771

- **Use case**: File paths, table patterns, flexible naming schemes

772

- **Patterns**: `*` (multiple characters), `?` (single character)

773

- **Implementation**: `RangerDefaultResourceMatcher`

774

775

### Hierarchical Matching

776

- **Use case**: File systems, directory structures, nested resources

777

- **Features**: Recursive matching, parent-child relationships

778

- **Implementation**: `RangerPathResourceMatcher`

779

780

### Regular Expression Matching

781

- **Use case**: Complex patterns, validation rules, advanced filtering

782

- **Features**: Full regex support, capture groups, flags

783

- **Implementation**: `RangerRegexResourceMatcher`

784

785

## Performance Optimization

786

787

Resource matching can impact policy evaluation performance:

788

789

### Compilation Caching

790

- **Pattern compilation**: Cache compiled patterns (regex, wildcards)

791

- **Matcher instances**: Reuse matcher instances for same resource types

792

- **Evaluation context**: Cache evaluation results when possible

793

794

### Match Scope Optimization

795

- **Scope determination**: Use `MatchScope` to optimize policy selection

796

- **Early termination**: Stop matching when scope is exceeded

797

- **Index-based lookup**: Use resource indexes for faster policy discovery

798

799

### Memory Management

800

- **Pattern limits**: Limit pattern complexity to prevent memory issues

801

- **Cache sizing**: Configure appropriate cache sizes for patterns

802

- **Cleanup**: Properly cleanup compiled patterns and matchers

803

804

## Configuration and Customization

805

806

Resource matchers support extensive configuration:

807

808

### Service Definition Configuration

809

```java

810

RangerResourceDef resourceDef = new RangerResourceDef();

811

resourceDef.setName("path");

812

resourceDef.setMatcher("org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher");

813

814

Map<String, String> matcherOptions = new HashMap<>();

815

matcherOptions.put("path.separator", "/");

816

matcherOptions.put("case.sensitive", "true");

817

matcherOptions.put("normalize.paths", "true");

818

resourceDef.setMatcherOptions(matcherOptions);

819

```

820

821

### Runtime Options

822

- **Case sensitivity**: Control case-sensitive matching

823

- **Path separators**: Configure path separator characters

824

- **Normalization**: Enable path and value normalization

825

- **Regex flags**: Set regular expression compilation flags

826

827

### Custom Matchers

828

Implement `RangerResourceMatcher` or extend `RangerAbstractResourceMatcher` for custom matching logic tailored to specific resource types and business requirements.