67
67
import java .util .Set ;
68
68
import java .util .concurrent .Executor ;
69
69
import java .util .concurrent .atomic .AtomicReference ;
70
- import java .util .function .Consumer ;
71
70
import java .util .function .Supplier ;
72
71
73
72
public final class EncryptedRepository extends BlobStoreRepository {
@@ -271,11 +270,15 @@ public void finalizeSnapshot(SnapshotId snapshotId, ShardGenerations shardGenera
271
270
int totalShards , List <SnapshotShardFailure > shardFailures , long repositoryStateId ,
272
271
boolean includeGlobalState , MetaData clusterMetaData , Map <String , Object > userMetadata ,
273
272
Version repositoryMetaVersion , ActionListener <SnapshotInfo > listener ) {
274
- validateRepositoryPasswordHash ( userMetadata , listener :: onFailure );
275
- if ( userMetadata != null && userMetadata . containsKey ( PASSWORD_HASH_RESERVED_USER_METADATA_KEY )) {
273
+ try {
274
+ validateRepositoryPasswordHash ( userMetadata );
276
275
// remove the repository password hash from the snapshot metadata, after all repository password verifications
277
276
// have completed, so that the hash is not displayed in the API response to the user
277
+ userMetadata = new HashMap <>(userMetadata );
278
278
userMetadata .remove (PASSWORD_HASH_RESERVED_USER_METADATA_KEY );
279
+ } catch (Exception passValidationException ) {
280
+ listener .onFailure (passValidationException );
281
+ return ;
279
282
}
280
283
super .finalizeSnapshot (snapshotId , shardGenerations , startTime , failure , totalShards , shardFailures , repositoryStateId ,
281
284
includeGlobalState , clusterMetaData , userMetadata , repositoryMetaVersion , listener );
@@ -285,7 +288,12 @@ public void finalizeSnapshot(SnapshotId snapshotId, ShardGenerations shardGenera
285
288
public void snapshotShard (Store store , MapperService mapperService , SnapshotId snapshotId , IndexId indexId ,
286
289
IndexCommit snapshotIndexCommit , IndexShardSnapshotStatus snapshotStatus , Version repositoryMetaVersion ,
287
290
Map <String , Object > userMetadata , ActionListener <String > listener ) {
288
- validateRepositoryPasswordHash (userMetadata , listener ::onFailure );
291
+ try {
292
+ validateRepositoryPasswordHash (userMetadata );
293
+ } catch (Exception passValidationException ) {
294
+ listener .onFailure (passValidationException );
295
+ return ;
296
+ }
289
297
super .snapshotShard (store , mapperService , snapshotId , indexId , snapshotIndexCommit , snapshotStatus , repositoryMetaVersion ,
290
298
userMetadata , listener );
291
299
}
@@ -771,25 +779,28 @@ private static String computeSaltedPBKDF2Hash(byte[] salt, char[] password) {
771
779
}
772
780
773
781
/**
774
- * Called before every snapshot operation on every node to validate that the snapshot metadata contains a password hash
775
- * that matches up with the repository password on the local node .
782
+ * Called before the shard snapshot and finalize operations, on the data and master nodes. This validates that the repository
783
+ * password hash of the master node that started the snapshot operation matches with the repository password on the data nodes .
776
784
*
777
785
* @param snapshotUserMetadata the snapshot metadata to verify
778
- * @param exception the exception handler to call when the repository password check fails
786
+ * @throws RepositoryException if the repository password on the local node mismatches or cannot be verified from the
787
+ * master's password hash from {@code snapshotUserMetadata}
779
788
*/
780
- private void validateRepositoryPasswordHash (Map <String , Object > snapshotUserMetadata , Consumer <Exception > exception ) {
781
- Object repositoryPasswordHash = snapshotUserMetadata .get (PASSWORD_HASH_RESERVED_USER_METADATA_KEY );
789
+ private void validateRepositoryPasswordHash (Map <String , Object > snapshotUserMetadata ) throws RepositoryException {
790
+ if (snapshotUserMetadata == null ) {
791
+ throw new RepositoryException (metadata .name (), "Unexpected fatal internal error" ,
792
+ new IllegalStateException ("Null snapshot metadata" ));
793
+ }
794
+ final Object repositoryPasswordHash = snapshotUserMetadata .get (PASSWORD_HASH_RESERVED_USER_METADATA_KEY );
782
795
if (repositoryPasswordHash == null || (false == repositoryPasswordHash instanceof String )) {
783
- exception .accept (new RepositoryException (metadata .name (), "Unexpected fatal internal error" ,
784
- new IllegalStateException ("Snapshot metadata does not contain the repository password hash as a String" )));
785
- return ;
796
+ throw new RepositoryException (metadata .name (), "Unexpected fatal internal error" ,
797
+ new IllegalStateException ("Snapshot metadata does not contain the repository password hash as a String" ));
786
798
}
787
799
if (false == passwordHashVerifier .verify ((String ) repositoryPasswordHash )) {
788
- exception . accept ( new RepositoryException (metadata .name (),
800
+ throw new RepositoryException (metadata .name (),
789
801
"Repository password mismatch. The local node's value of the keystore secure setting [" +
790
802
EncryptedRepositoryPlugin .ENCRYPTION_PASSWORD_SETTING .getConcreteSettingForNamespace (metadata .name ()).getKey () +
791
- "] is different from the elected master node, which started the snapshot operation" ));
792
- return ;
803
+ "] is different from the elected master node, which started the snapshot operation" );
793
804
}
794
805
}
795
806
0 commit comments