31
31
import org .elasticsearch .cluster .metadata .IndexMetadata ;
32
32
import org .elasticsearch .cluster .metadata .MappingMetadata ;
33
33
import org .elasticsearch .cluster .metadata .Metadata ;
34
+ import org .elasticsearch .cluster .metadata .ReservedStateMetadata ;
34
35
import org .elasticsearch .cluster .routing .IndexRoutingTable ;
35
36
import org .elasticsearch .cluster .service .ClusterService ;
36
37
import org .elasticsearch .core .TimeValue ;
46
47
import org .elasticsearch .rest .RestStatus ;
47
48
import org .elasticsearch .threadpool .Scheduler ;
48
49
import org .elasticsearch .xcontent .XContentType ;
50
+ import org .elasticsearch .xpack .core .security .authz .RoleMappingMetadata ;
49
51
import org .elasticsearch .xpack .security .SecurityFeatures ;
52
+ import org .elasticsearch .xpack .security .action .rolemapping .ReservedRoleMappingAction ;
50
53
51
54
import java .time .Instant ;
55
+ import java .util .Arrays ;
52
56
import java .util .List ;
53
57
import java .util .Map ;
54
58
import java .util .Objects ;
74
78
public class SecurityIndexManager implements ClusterStateListener {
75
79
76
80
public static final String SECURITY_VERSION_STRING = "security-version" ;
77
-
81
+ private static final String FILE_SETTINGS_METADATA_NAMESPACE = "file_settings" ;
82
+ private static final String HANDLER_ROLE_MAPPINGS_NAME = "role_mappings" ;
78
83
private static final Logger logger = LogManager .getLogger (SecurityIndexManager .class );
79
84
80
85
/**
@@ -267,6 +272,11 @@ private static boolean isCreatedOnLatestVersion(IndexMetadata indexMetadata) {
267
272
return indexVersionCreated != null && indexVersionCreated .onOrAfter (IndexVersion .current ());
268
273
}
269
274
275
+ private static Set <String > getFileSettingsMetadataHandlerRoleMappingKeys (ClusterState clusterState ) {
276
+ ReservedStateMetadata fileSettingsMetadata = clusterState .metadata ().reservedStateMetadata ().get (FILE_SETTINGS_METADATA_NAMESPACE );
277
+ return fileSettingsMetadata .handlers ().get (HANDLER_ROLE_MAPPINGS_NAME ).keys ();
278
+ }
279
+
270
280
@ Override
271
281
public void clusterChanged (ClusterChangedEvent event ) {
272
282
if (event .state ().blocks ().hasGlobalBlock (GatewayService .STATE_NOT_RECOVERED_BLOCK )) {
@@ -284,6 +294,10 @@ public void clusterChanged(ClusterChangedEvent event) {
284
294
Tuple <Boolean , Boolean > available = checkIndexAvailable (event .state ());
285
295
final boolean indexAvailableForWrite = available .v1 ();
286
296
final boolean indexAvailableForSearch = available .v2 ();
297
+ final Set <String > reservedStateRoleMappingNames = getFileSettingsMetadataHandlerRoleMappingKeys (event .state ());
298
+ final boolean reservedRoleMappingsSynced = reservedStateRoleMappingNames .size () == RoleMappingMetadata .getFromClusterState (
299
+ event .state ()
300
+ ).getRoleMappings ().size ();
287
301
final boolean mappingIsUpToDate = indexMetadata == null || checkIndexMappingUpToDate (event .state ());
288
302
final int migrationsVersion = getMigrationVersionFromIndexMetadata (indexMetadata );
289
303
final SystemIndexDescriptor .MappingsVersion minClusterMappingVersion = getMinSecurityIndexMappingVersion (event .state ());
@@ -314,6 +328,7 @@ public void clusterChanged(ClusterChangedEvent event) {
314
328
indexAvailableForWrite ,
315
329
mappingIsUpToDate ,
316
330
createdOnLatestVersion ,
331
+ reservedRoleMappingsSynced ,
317
332
migrationsVersion ,
318
333
minClusterMappingVersion ,
319
334
indexMappingVersion ,
@@ -323,7 +338,8 @@ public void clusterChanged(ClusterChangedEvent event) {
323
338
indexUUID ,
324
339
allSecurityFeatures .stream ()
325
340
.filter (feature -> featureService .clusterHasFeature (event .state (), feature ))
326
- .collect (Collectors .toSet ())
341
+ .collect (Collectors .toSet ()),
342
+ reservedStateRoleMappingNames
327
343
);
328
344
this .state = newState ;
329
345
@@ -334,6 +350,10 @@ public void clusterChanged(ClusterChangedEvent event) {
334
350
}
335
351
}
336
352
353
+ public Set <String > getReservedStateRoleMappingNames () {
354
+ return state .reservedStateRoleMappingNames ;
355
+ }
356
+
337
357
public static int getMigrationVersionFromIndexMetadata (IndexMetadata indexMetadata ) {
338
358
Map <String , String > customMetadata = indexMetadata == null ? null : indexMetadata .getCustomData (MIGRATION_VERSION_CUSTOM_KEY );
339
359
if (customMetadata == null ) {
@@ -438,7 +458,8 @@ private Tuple<Boolean, Boolean> checkIndexAvailable(ClusterState state) {
438
458
439
459
public boolean isEligibleSecurityMigration (SecurityMigrations .SecurityMigration securityMigration ) {
440
460
return state .securityFeatures .containsAll (securityMigration .nodeFeaturesRequired ())
441
- && state .indexMappingVersion >= securityMigration .minMappingVersion ();
461
+ && state .indexMappingVersion >= securityMigration .minMappingVersion ()
462
+ && securityMigration .checkPreConditions (state );
442
463
}
443
464
444
465
public boolean isReadyForSecurityMigration (SecurityMigrations .SecurityMigration securityMigration ) {
@@ -671,13 +692,15 @@ public static class State {
671
692
false ,
672
693
false ,
673
694
false ,
695
+ false ,
674
696
null ,
675
697
null ,
676
698
null ,
677
699
null ,
678
700
null ,
679
701
null ,
680
702
null ,
703
+ Set .of (),
681
704
Set .of ()
682
705
);
683
706
public final Instant creationTime ;
@@ -686,6 +709,7 @@ public static class State {
686
709
public final boolean indexAvailableForWrite ;
687
710
public final boolean mappingUpToDate ;
688
711
public final boolean createdOnLatestVersion ;
712
+ public final boolean reservedRoleMappingsSynced ;
689
713
public final Integer migrationsVersion ;
690
714
// Min mapping version supported by the descriptors in the cluster
691
715
public final SystemIndexDescriptor .MappingsVersion minClusterMappingVersion ;
@@ -696,6 +720,7 @@ public static class State {
696
720
public final IndexMetadata .State indexState ;
697
721
public final String indexUUID ;
698
722
public final Set <NodeFeature > securityFeatures ;
723
+ public final Set <String > reservedStateRoleMappingNames ;
699
724
700
725
public State (
701
726
Instant creationTime ,
@@ -704,14 +729,16 @@ public State(
704
729
boolean indexAvailableForWrite ,
705
730
boolean mappingUpToDate ,
706
731
boolean createdOnLatestVersion ,
732
+ boolean reservedRoleMappingsSynced ,
707
733
Integer migrationsVersion ,
708
734
SystemIndexDescriptor .MappingsVersion minClusterMappingVersion ,
709
735
Integer indexMappingVersion ,
710
736
String concreteIndexName ,
711
737
ClusterHealthStatus indexHealth ,
712
738
IndexMetadata .State indexState ,
713
739
String indexUUID ,
714
- Set <NodeFeature > securityFeatures
740
+ Set <NodeFeature > securityFeatures ,
741
+ Set <String > reservedStateRoleMappingNames
715
742
) {
716
743
this .creationTime = creationTime ;
717
744
this .isIndexUpToDate = isIndexUpToDate ;
@@ -720,13 +747,15 @@ public State(
720
747
this .mappingUpToDate = mappingUpToDate ;
721
748
this .migrationsVersion = migrationsVersion ;
722
749
this .createdOnLatestVersion = createdOnLatestVersion ;
750
+ this .reservedRoleMappingsSynced = reservedRoleMappingsSynced ;
723
751
this .minClusterMappingVersion = minClusterMappingVersion ;
724
752
this .indexMappingVersion = indexMappingVersion ;
725
753
this .concreteIndexName = concreteIndexName ;
726
754
this .indexHealth = indexHealth ;
727
755
this .indexState = indexState ;
728
756
this .indexUUID = indexUUID ;
729
757
this .securityFeatures = securityFeatures ;
758
+ this .reservedStateRoleMappingNames = reservedStateRoleMappingNames ;
730
759
}
731
760
732
761
@ Override
@@ -740,13 +769,15 @@ public boolean equals(Object o) {
740
769
&& indexAvailableForWrite == state .indexAvailableForWrite
741
770
&& mappingUpToDate == state .mappingUpToDate
742
771
&& createdOnLatestVersion == state .createdOnLatestVersion
772
+ && reservedRoleMappingsSynced == state .reservedRoleMappingsSynced
743
773
&& Objects .equals (indexMappingVersion , state .indexMappingVersion )
744
774
&& Objects .equals (migrationsVersion , state .migrationsVersion )
745
775
&& Objects .equals (minClusterMappingVersion , state .minClusterMappingVersion )
746
776
&& Objects .equals (concreteIndexName , state .concreteIndexName )
747
777
&& indexHealth == state .indexHealth
748
778
&& indexState == state .indexState
749
- && Objects .equals (securityFeatures , state .securityFeatures );
779
+ && Objects .equals (securityFeatures , state .securityFeatures )
780
+ && Objects .equals (reservedStateRoleMappingNames , state .reservedStateRoleMappingNames );
750
781
}
751
782
752
783
public boolean indexExists () {
@@ -762,12 +793,14 @@ public int hashCode() {
762
793
indexAvailableForWrite ,
763
794
mappingUpToDate ,
764
795
createdOnLatestVersion ,
796
+ reservedRoleMappingsSynced ,
765
797
migrationsVersion ,
766
798
minClusterMappingVersion ,
767
799
indexMappingVersion ,
768
800
concreteIndexName ,
769
801
indexHealth ,
770
- securityFeatures
802
+ securityFeatures ,
803
+ reservedStateRoleMappingNames
771
804
);
772
805
}
773
806
@@ -786,6 +819,8 @@ public String toString() {
786
819
+ mappingUpToDate
787
820
+ ", createdOnLatestVersion="
788
821
+ createdOnLatestVersion
822
+ + ", reservedRoleMappingsSynced="
823
+ + reservedRoleMappingsSynced
789
824
+ ", migrationsVersion="
790
825
+ migrationsVersion
791
826
+ ", minClusterMappingVersion="
@@ -804,6 +839,9 @@ public String toString() {
804
839
+ '\''
805
840
+ ", securityFeatures="
806
841
+ securityFeatures
842
+ + ", reservedStateRoleMappingNames=["
843
+ + Arrays .toString (reservedStateRoleMappingNames .toArray (String []::new ))
844
+ + "]"
807
845
+ '}' ;
808
846
}
809
847
}
0 commit comments