diff --git a/CHANGELOG.md b/CHANGELOG.md index 4786c353b697d..eee9ba38dfd87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Allow the truncate filter in normalizers ([#19778](https://github.com/opensearch-project/OpenSearch/issues/19778)) - Support pull-based ingestion message mappers and raw payload support ([#19765](https://github.com/opensearch-project/OpenSearch/pull/19765)) - Support dynamic consumer configuration update in pull-based ingestion ([#19963](https://github.com/opensearch-project/OpenSearch/pull/19963)) - +- Add validation to make crypto store settings immutable ([#20123](https://github.com/opensearch-project/OpenSearch/pull/20123)) ### Changed - Faster `terms` query creation for `keyword` field with index and docValues enabled ([#19350](https://github.com/opensearch-project/OpenSearch/pull/19350)) - Refactor to move prepareIndex and prepareDelete methods to Engine class ([#19551](https://github.com/opensearch-project/OpenSearch/pull/19551)) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/MetadataUpdateSettingsService.java b/server/src/main/java/org/opensearch/cluster/metadata/MetadataUpdateSettingsService.java index fb512a0f7ea13..e57a2635b8a68 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/MetadataUpdateSettingsService.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/MetadataUpdateSettingsService.java @@ -142,6 +142,7 @@ public void updateSettings( validateRefreshIntervalSettings(normalizedSettings, clusterService.getClusterSettings()); validateTranslogDurabilitySettings(normalizedSettings, clusterService.getClusterSettings(), clusterService.getSettings()); validateIndexTotalPrimaryShardsPerNodeSetting(normalizedSettings, clusterService); + validateCryptoStoreSettings(normalizedSettings, request.indices(), clusterService.state()); final int defaultReplicaCount = clusterService.getClusterSettings().get(Metadata.DEFAULT_REPLICA_COUNT_SETTING); Settings.Builder settingsForClosedIndices = Settings.builder(); @@ -589,4 +590,33 @@ public static void validateIndexTotalPrimaryShardsPerNodeSetting(Settings indexS ); } } + + /** + * Validates crypto store settings are immutable after index creation. + */ + public static void validateCryptoStoreSettings(Settings indexSettings, Index[] indices, ClusterState clusterState) { + final String storeTypeKey = "index.store.type"; + + // Only validate if store.type is being explicitly modified + if (!indexSettings.keySet().contains(storeTypeKey)) { + return; + } + + for (Index index : indices) { + String currentStoreType = clusterState.metadata().getIndexSafe(index).getSettings().get(storeTypeKey, ""); + String newStoreType = indexSettings.get(storeTypeKey); + + // Prevent changing FROM cryptofs to anything else (including null) + if ("cryptofs".equals(currentStoreType) && !"cryptofs".equals(newStoreType)) { + throw new IllegalArgumentException( + "Cannot change store type from 'cryptofs' for index [" + index.getName() + "] - cryptofs store type is immutable" + ); + } + + // Prevent changing TO cryptofs from any other type + if (!"cryptofs".equals(currentStoreType) && "cryptofs".equals(newStoreType)) { + throw new IllegalArgumentException("Cannot change store type to 'cryptofs' for index [" + index.getName() + "]"); + } + } + } }