38
38
import org .opensearch .common .util .concurrent .ThreadContext ;
39
39
import org .opensearch .core .common .unit .ByteSizeUnit ;
40
40
import org .opensearch .core .common .unit .ByteSizeValue ;
41
+ import org .opensearch .security .action .apitokens .ApiToken ;
42
+ import org .opensearch .security .action .apitokens .ApiTokenRepository ;
43
+ import org .opensearch .security .action .apitokens .Permissions ;
41
44
import org .opensearch .security .resolver .IndexResolverReplacer ;
42
45
import org .opensearch .security .securityconf .FlattenedActionGroups ;
43
46
import org .opensearch .security .securityconf .impl .CType ;
44
47
import org .opensearch .security .securityconf .impl .SecurityDynamicConfiguration ;
48
+ import org .opensearch .security .securityconf .impl .v7 .ActionGroupsV7 ;
45
49
import org .opensearch .security .securityconf .impl .v7 .RoleV7 ;
46
50
import org .opensearch .security .user .User ;
47
51
import org .opensearch .security .util .MockIndexMetadataBuilder ;
48
52
53
+ import org .mockito .Mockito ;
54
+
49
55
import static org .hamcrest .MatcherAssert .assertThat ;
50
56
import static org .opensearch .security .privileges .PrivilegeEvaluatorResponseMatcher .isAllowed ;
51
57
import static org .opensearch .security .privileges .PrivilegeEvaluatorResponseMatcher .isForbidden ;
@@ -280,6 +286,69 @@ public void hasAny_wildcard() throws Exception {
280
286
isForbidden (missingPrivileges ("cluster:whatever" ))
281
287
);
282
288
}
289
+
290
+ @ Test
291
+ public void apiToken_explicit_failsWithWildcard () throws Exception {
292
+ SecurityDynamicConfiguration <RoleV7 > roles = SecurityDynamicConfiguration .empty (CType .ROLES );
293
+ ActionPrivileges subject = new ActionPrivileges (roles , FlattenedActionGroups .EMPTY , null , Settings .EMPTY );
294
+ String token = "blah" ;
295
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
296
+ "apitoken:" + token ,
297
+ new Permissions (List .of ("*" ), List .of ())
298
+ );
299
+ // Explicit fails
300
+ assertThat (
301
+ subject .hasExplicitClusterPrivilege (context , "cluster:whatever" ),
302
+ isForbidden (missingPrivileges ("cluster:whatever" ))
303
+ );
304
+ // Not explicit succeeds
305
+ assertThat (subject .hasClusterPrivilege (context , "cluster:whatever" ), isAllowed ());
306
+ // Any succeeds
307
+ assertThat (subject .hasAnyClusterPrivilege (context , ImmutableSet .of ("cluster:whatever" )), isAllowed ());
308
+ }
309
+
310
+ @ Test
311
+ public void apiToken_succeedsWithExactMatch () throws Exception {
312
+ SecurityDynamicConfiguration <RoleV7 > roles = SecurityDynamicConfiguration .empty (CType .ROLES );
313
+ ActionPrivileges subject = new ActionPrivileges (roles , FlattenedActionGroups .EMPTY , null , Settings .EMPTY );
314
+ String token = "blah" ;
315
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
316
+ "apitoken:" + token ,
317
+ new Permissions (List .of ("cluster:whatever" ), List .of ())
318
+ );
319
+ // Explicit succeeds
320
+ assertThat (subject .hasExplicitClusterPrivilege (context , "cluster:whatever" ), isAllowed ());
321
+ // Not explicit succeeds
322
+ assertThat (subject .hasClusterPrivilege (context , "cluster:whatever" ), isAllowed ());
323
+ // Any succeeds
324
+ assertThat (subject .hasAnyClusterPrivilege (context , ImmutableSet .of ("cluster:whatever" )), isAllowed ());
325
+ // Any succeeds
326
+ assertThat (subject .hasAnyClusterPrivilege (context , ImmutableSet .of ("cluster:whatever" , "cluster:other" )), isAllowed ());
327
+ }
328
+
329
+ @ Test
330
+ public void apiToken_succeedsWithActionGroupsExapnded () throws Exception {
331
+ SecurityDynamicConfiguration <RoleV7 > roles = SecurityDynamicConfiguration .empty (CType .ROLES );
332
+
333
+ SecurityDynamicConfiguration <ActionGroupsV7 > config = SecurityDynamicConfiguration .fromYaml (
334
+ "CLUSTER_ALL:\n allowed_actions:\n - \" cluster:*\" " ,
335
+ CType .ACTIONGROUPS
336
+ );
337
+
338
+ FlattenedActionGroups actionGroups = new FlattenedActionGroups (config );
339
+ ActionPrivileges subject = new ActionPrivileges (roles , actionGroups , null , Settings .EMPTY );
340
+ String token = "blah" ;
341
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
342
+ "apitoken:" + token ,
343
+ new Permissions (List .of ("CLUSTER_ALL" ), List .of ())
344
+ );
345
+ // Explicit succeeds
346
+ assertThat (subject .hasExplicitClusterPrivilege (context , "cluster:whatever" ), isAllowed ());
347
+ // Not explicit succeeds
348
+ assertThat (subject .hasClusterPrivilege (context , "cluster:whatever" ), isAllowed ());
349
+ // Any succeeds
350
+ assertThat (subject .hasClusterPrivilege (context , "cluster:monitor/main" ), isAllowed ());
351
+ }
283
352
}
284
353
285
354
/**
@@ -314,9 +383,20 @@ public void positive_full() throws Exception {
314
383
assertThat (result , isAllowed ());
315
384
}
316
385
386
+ @ Test
387
+ public void apiTokens_positive_full () throws Exception {
388
+ String token = "blah" ;
389
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
390
+ "apitoken:" + token ,
391
+ new Permissions (List .of ("index_a11" ), List .of (new ApiToken .IndexPermission (List .of ("index_a11" ), List .of ("*" ))))
392
+ );
393
+ PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (context , requiredActions , resolved ("index_a11" ));
394
+ assertThat (result , isAllowed ());
395
+ }
396
+
317
397
@ Test
318
398
public void positive_partial () throws Exception {
319
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
399
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
320
400
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , requiredActions , resolved ("index_a11" , "index_a12" ));
321
401
322
402
if (covers (ctx , "index_a11" , "index_a12" )) {
@@ -330,7 +410,7 @@ public void positive_partial() throws Exception {
330
410
331
411
@ Test
332
412
public void positive_partial2 () throws Exception {
333
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
413
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
334
414
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (
335
415
ctx ,
336
416
requiredActions ,
@@ -363,14 +443,26 @@ public void positive_noLocal() throws Exception {
363
443
364
444
@ Test
365
445
public void negative_wrongRole () throws Exception {
366
- PrivilegesEvaluationContext ctx = ctx ("other_role" );
446
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("other_role" );
367
447
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , requiredActions , resolved ("index_a11" ));
368
448
assertThat (result , isForbidden (missingPrivileges (requiredActions )));
369
449
}
370
450
451
+ @ Test
452
+ public void apiToken_negative_noPermissions () throws Exception {
453
+ String token = "blah" ;
454
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
455
+ "apitoken:" + token ,
456
+ new Permissions (List .of (), List .of (new ApiToken .IndexPermission (List .of (), List .of ())))
457
+ );
458
+
459
+ PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (context , requiredActions , resolved ("index_a11" ));
460
+ assertThat (result , isForbidden ());
461
+ }
462
+
371
463
@ Test
372
464
public void negative_wrongAction () throws Exception {
373
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
465
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
374
466
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , otherActions , resolved ("index_a11" ));
375
467
376
468
if (actionSpec .givenPrivs .contains ("*" )) {
@@ -382,7 +474,7 @@ public void negative_wrongAction() throws Exception {
382
474
383
475
@ Test
384
476
public void positive_hasExplicit_full () {
385
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
477
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
386
478
PrivilegesEvaluatorResponse result = subject .hasExplicitIndexPrivilege (ctx , requiredActions , resolved ("index_a11" ));
387
479
388
480
if (actionSpec .givenPrivs .contains ("*" )) {
@@ -397,7 +489,21 @@ public void positive_hasExplicit_full() {
397
489
}
398
490
}
399
491
400
- private boolean covers (PrivilegesEvaluationContext ctx , String ... indices ) {
492
+ @ Test
493
+ public void apiTokens_positive_hasExplicit_full () {
494
+ String token = "blah" ;
495
+ PermissionBasedPrivilegesEvaluationContext context = ctxForApiToken (
496
+ "apitoken:" + token ,
497
+ new Permissions (List .of ("index_a11" ), List .of (new ApiToken .IndexPermission (List .of ("index_a11" ), List .of ("*" ))))
498
+ );
499
+
500
+ PrivilegesEvaluatorResponse result = subject .hasExplicitIndexPrivilege (context , requiredActions , resolved ("index_a11" ));
501
+
502
+ assertThat (result , isForbidden ());
503
+
504
+ }
505
+
506
+ private boolean covers (RoleBasedPrivilegesEvaluationContext ctx , String ... indices ) {
401
507
for (String index : indices ) {
402
508
if (!indexSpec .covers (ctx .getUser (), index )) {
403
509
return false ;
@@ -522,7 +628,7 @@ public static class DataStreams {
522
628
523
629
@ Test
524
630
public void positive_full () throws Exception {
525
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
631
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
526
632
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , requiredActions , resolved ("data_stream_a11" ));
527
633
if (covers (ctx , "data_stream_a11" )) {
528
634
assertThat (result , isAllowed ());
@@ -538,7 +644,7 @@ public void positive_full() throws Exception {
538
644
539
645
@ Test
540
646
public void positive_partial () throws Exception {
541
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
647
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
542
648
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (
543
649
ctx ,
544
650
requiredActions ,
@@ -569,19 +675,19 @@ public void positive_partial() throws Exception {
569
675
570
676
@ Test
571
677
public void negative_wrongRole () throws Exception {
572
- PrivilegesEvaluationContext ctx = ctx ("other_role" );
678
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("other_role" );
573
679
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , requiredActions , resolved ("data_stream_a11" ));
574
680
assertThat (result , isForbidden (missingPrivileges (requiredActions )));
575
681
}
576
682
577
683
@ Test
578
684
public void negative_wrongAction () throws Exception {
579
- PrivilegesEvaluationContext ctx = ctx ("test_role" );
685
+ RoleBasedPrivilegesEvaluationContext ctx = ctx ("test_role" );
580
686
PrivilegesEvaluatorResponse result = subject .hasIndexPrivilege (ctx , otherActions , resolved ("data_stream_a11" ));
581
687
assertThat (result , isForbidden (missingPrivileges (otherActions )));
582
688
}
583
689
584
- private boolean covers (PrivilegesEvaluationContext ctx , String ... indices ) {
690
+ private boolean covers (RoleBasedPrivilegesEvaluationContext ctx , String ... indices ) {
585
691
for (String index : indices ) {
586
692
if (!indexSpec .covers (ctx .getUser (), index )) {
587
693
return false ;
@@ -1039,10 +1145,15 @@ static SecurityDynamicConfiguration<RoleV7> createRoles(int numberOfRoles, int n
1039
1145
}
1040
1146
}
1041
1147
1042
- static PrivilegesEvaluationContext ctx (String ... roles ) {
1043
- User user = new User ("test_user" );
1148
+ static RoleBasedPrivilegesEvaluationContext ctx (String ... roles ) {
1149
+ return ctxWithUserName ("test-user" , roles );
1150
+ }
1151
+
1152
+ static RoleBasedPrivilegesEvaluationContext ctxWithUserName (String userName , String ... roles ) {
1153
+ User user = new User (userName );
1044
1154
user .addAttributes (ImmutableMap .of ("attrs.dept_no" , "a11" ));
1045
- return new PrivilegesEvaluationContext (
1155
+ ApiTokenRepository mockRepository = Mockito .mock (ApiTokenRepository .class );
1156
+ return new RoleBasedPrivilegesEvaluationContext (
1046
1157
user ,
1047
1158
ImmutableSet .copyOf (roles ),
1048
1159
null ,
@@ -1054,10 +1165,25 @@ static PrivilegesEvaluationContext ctx(String... roles) {
1054
1165
);
1055
1166
}
1056
1167
1057
- static PrivilegesEvaluationContext ctxByUsername (String username ) {
1168
+ static PermissionBasedPrivilegesEvaluationContext ctxForApiToken (String userName , Permissions permissions ) {
1169
+ User user = new User (userName );
1170
+ user .addAttributes (ImmutableMap .of ("attrs.dept_no" , "a11" ));
1171
+ return new PermissionBasedPrivilegesEvaluationContext (
1172
+ user ,
1173
+ null ,
1174
+ null ,
1175
+ null ,
1176
+ null ,
1177
+ new IndexNameExpressionResolver (new ThreadContext (Settings .EMPTY )),
1178
+ null ,
1179
+ permissions
1180
+ );
1181
+ }
1182
+
1183
+ static RoleBasedPrivilegesEvaluationContext ctxByUsername (String username ) {
1058
1184
User user = new User (username );
1059
1185
user .addAttributes (ImmutableMap .of ("attrs.dept_no" , "a11" ));
1060
- return new PrivilegesEvaluationContext (
1186
+ return new RoleBasedPrivilegesEvaluationContext (
1061
1187
user ,
1062
1188
ImmutableSet .of (),
1063
1189
null ,
0 commit comments