Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Use Lucene `pack` method for `half_float` and `usigned_long` when using `ApproximatePointRangeQuery`.
- Add a mapper for context aware segments grouping criteria ([#19233](https://github.com/opensearch-project/OpenSearch/pull/19233))
- Return full error for GRPC error response ([#19568](https://github.com/opensearch-project/OpenSearch/pull/19568))
- Add support for repository with Server side encryption enabled and client side encryption as well based on a flag. ([#19630)](https://github.com/opensearch-project/OpenSearch/pull/19630))
- Add pluggable gRPC interceptors with explicit ordering([#19005](https://github.com/opensearch-project/OpenSearch/pull/19005))
- Add BindableServices extension point to transport-grpc-spi ([#19304](https://github.com/opensearch-project/OpenSearch/pull/19304))
- Add metrics for the merged segment warmer feature ([#18929](https://github.com/opensearch-project/OpenSearch/pull/18929))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public boolean serverSideEncryptionBucketKey() {
* null as the S3 client ignores null header values
*/
public String serverSideEncryptionEncryptionContext() {
return serverSideEncryptionEncryptionContext.isEmpty()
return serverSideEncryptionEncryptionContext == null || serverSideEncryptionEncryptionContext.isEmpty()
? null
: Base64.getEncoder().encodeToString(serverSideEncryptionEncryptionContext.getBytes(StandardCharsets.UTF_8));
}
Expand All @@ -239,7 +239,7 @@ public String serverSideEncryptionEncryptionContext() {
* Returns the expected bucket owner if set, else null as the S3 client ignores null header values
*/
public String expectedBucketOwner() {
return expectedBucketOwner.isEmpty() ? null : expectedBucketOwner;
return expectedBucketOwner == null || expectedBucketOwner.isEmpty() ? null : expectedBucketOwner;
}

public long bufferSizeInBytes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -683,4 +683,10 @@ protected void doClose() {
}
super.doClose();
}

@Override
public boolean isSeverSideEncryptionEnabled() {
// s3 is always server side encrypted.
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
package org.opensearch.repositories.s3;

import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ServerSideEncryption;

import org.opensearch.cluster.metadata.RepositoryMetadata;
import org.opensearch.common.blobstore.BlobStoreException;
Expand Down Expand Up @@ -175,6 +176,18 @@ public void testValidateHttpLClientType_Invalid_Values() {
}
}

public void testIsSeverSideEncryptionEnabled_When_AWSKMS_Type() {
Settings settings = Settings.builder()
.put(S3Repository.SERVER_SIDE_ENCRYPTION_TYPE_SETTING.getKey(), ServerSideEncryption.AWS_KMS.toString())
.build();
final RepositoryMetadata metadata = new RepositoryMetadata("dummy-repo", "mock", settings);
try (S3Repository s3Repo = createS3Repo(metadata)) {

// Don't expect any Exception
assertTrue(s3Repo.isSeverSideEncryptionEnabled());
}
}

private S3Repository createS3Repo(RepositoryMetadata metadata) {
return new S3Repository(
metadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ private Map<String, Map<String, Object>> getSegmentMetadata(
IndexMetadata.INDEX_REMOTE_SEGMENT_STORE_REPOSITORY_SETTING.get(indexMetadata.getSettings()),
index.getUUID(),
shardId,
indexSettings.getRemoteStorePathStrategy()
indexSettings.getRemoteStorePathStrategy(),
null,
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexSettings.getIndexMetadata())
);

Map<String, RemoteSegmentMetadata> segmentMetadataMapWithFilenames = remoteDirectory.readLatestNMetadataFiles(5);
Expand Down Expand Up @@ -257,7 +259,8 @@ private Map<String, Map<String, Object>> getTranslogMetadataFiles(
tracker,
indexSettings.getRemoteStorePathStrategy(),
new RemoteStoreSettings(clusterService.getSettings(), clusterService.getClusterSettings()),
RemoteStoreUtils.determineTranslogMetadataEnabled(indexMetadata)
RemoteStoreUtils.determineTranslogMetadataEnabled(indexMetadata),
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexSettings.getIndexMetadata())
);

Map<String, TranslogTransferMetadata> metadataMap = manager.readLatestNMetadataFiles(5);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,7 @@ public Iterator<Setting<?>> settings() {
public static final String KEY_PRIMARY_TERMS = "primary_terms";
public static final String REMOTE_STORE_CUSTOM_KEY = "remote_store";
public static final String TRANSLOG_METADATA_KEY = "translog_metadata";
public static final String REMOTE_STORE_SSE_ENABLED_INDEX_KEY = "sse_enabled_index";
public static final String CONTEXT_KEY = "context";
public static final String INGESTION_SOURCE_KEY = "ingestion_source";
public static final String INGESTION_STATUS_KEY = "ingestion_status";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ static Optional<String> validateOverlap(Set<String> requestSettings, Settings co
IndexMetadata buildAndValidateTemporaryIndexMetadata(
final Settings aggregatedIndexSettings,
final CreateIndexClusterStateUpdateRequest request,
final int routingNumShards
final int routingNumShards,
final ClusterState clusterState
) {

final boolean isHiddenAfterTemplates = IndexMetadata.INDEX_HIDDEN_SETTING.get(aggregatedIndexSettings);
Expand All @@ -643,7 +644,7 @@ IndexMetadata buildAndValidateTemporaryIndexMetadata(
tmpImdBuilder.setRoutingNumShards(routingNumShards);
tmpImdBuilder.settings(aggregatedIndexSettings);
tmpImdBuilder.system(isSystem);
addRemoteStoreCustomMetadata(tmpImdBuilder, true);
addRemoteStoreCustomMetadata(tmpImdBuilder, true, clusterState);

if (request.context() != null) {
tmpImdBuilder.context(request.context());
Expand All @@ -662,7 +663,9 @@ IndexMetadata buildAndValidateTemporaryIndexMetadata(
* @param tmpImdBuilder index metadata builder.
* @param assertNullOldType flag to verify that the old remote store path type is null
*/
public void addRemoteStoreCustomMetadata(IndexMetadata.Builder tmpImdBuilder, boolean assertNullOldType) {
public void addRemoteStoreCustomMetadata(IndexMetadata.Builder tmpImdBuilder, boolean assertNullOldType, ClusterState clusterState) {

boolean isRestoreFromSnapshot = !assertNullOldType;
if (remoteStoreCustomMetadataResolver == null) {
return;
}
Expand All @@ -677,6 +680,24 @@ public void addRemoteStoreCustomMetadata(IndexMetadata.Builder tmpImdBuilder, bo
boolean isTranslogMetadataEnabled = remoteStoreCustomMetadataResolver.isTranslogMetadataEnabled();
remoteCustomData.put(IndexMetadata.TRANSLOG_METADATA_KEY, Boolean.toString(isTranslogMetadataEnabled));

Optional<DiscoveryNode> remoteNode = clusterState.nodes()
.getNodes()
.values()
.stream()
.filter(DiscoveryNode::isRemoteStoreNode)
.findFirst();

String sseEnabledIndex = existingCustomData == null
? null
: existingCustomData.get(IndexMetadata.REMOTE_STORE_SSE_ENABLED_INDEX_KEY);
if (isRestoreFromSnapshot && sseEnabledIndex != null) {
remoteCustomData.put(IndexMetadata.REMOTE_STORE_SSE_ENABLED_INDEX_KEY, sseEnabledIndex);
} else if (remoteNode.isPresent()
&& !isRestoreFromSnapshot
&& remoteStoreCustomMetadataResolver.isRemoteStoreRepoServerSideEncryptionEnabled()) {
remoteCustomData.put(IndexMetadata.REMOTE_STORE_SSE_ENABLED_INDEX_KEY, Boolean.toString(true));
}

// Determine the path type for use using the remoteStorePathResolver.
RemoteStorePathStrategy newPathStrategy = remoteStoreCustomMetadataResolver.getPathStrategy();
remoteCustomData.put(PathType.NAME, newPathStrategy.getType().name());
Expand Down Expand Up @@ -731,7 +752,7 @@ private ClusterState applyCreateIndexRequestWithV1Templates(
clusterService.getClusterSettings()
);
int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, null);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards, currentState);

return applyCreateIndexWithTemporaryService(
currentState,
Expand Down Expand Up @@ -796,7 +817,7 @@ private ClusterState applyCreateIndexRequestWithV2Template(
clusterService.getClusterSettings()
);
int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, null);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards, currentState);

return applyCreateIndexWithTemporaryService(
currentState,
Expand Down Expand Up @@ -880,7 +901,7 @@ private ClusterState applyCreateIndexRequestWithExistingMetadata(
clusterService.getClusterSettings()
);
final int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, sourceMetadata);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards);
IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards, currentState);

return applyCreateIndexWithTemporaryService(
currentState,
Expand Down Expand Up @@ -1178,8 +1199,8 @@ public static void updateRemoteStoreSettings(
.findFirst();

if (remoteNode.isPresent()) {
translogRepo = RemoteStoreNodeAttribute.getTranslogRepoName(remoteNode.get().getAttributes());
segmentRepo = RemoteStoreNodeAttribute.getSegmentRepoName(remoteNode.get().getAttributes());
translogRepo = RemoteStoreNodeAttribute.getTranslogRepoName(remoteNode.get().getAttributes());
if (segmentRepo != null) {
settingsBuilder.put(SETTING_REMOTE_STORE_ENABLED, true).put(SETTING_REMOTE_SEGMENT_STORE_REPOSITORY, segmentRepo);
if (translogRepo != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,8 @@ public void apply(Settings value, Settings current, Settings previous) {
RemoteStoreSettings.CLUSTER_REMOTE_STORE_PINNED_TIMESTAMP_ENABLED,
RemoteStoreSettings.CLUSTER_REMOTE_STORE_SEGMENTS_PATH_PREFIX,
RemoteStoreSettings.CLUSTER_REMOTE_STORE_TRANSLOG_PATH_PREFIX,
// Server Side encryption enabled
RemoteStoreSettings.CLUSTER_SERVER_SIDE_ENCRYPTION_ENABLED,

// Snapshot related Settings
BlobStoreRepository.SNAPSHOT_SHARD_PATH_PREFIX_SETTING,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.index.query.SearchIndexNameMatcher;
import org.opensearch.index.remote.RemoteStoreStatsTrackerFactory;
import org.opensearch.index.remote.RemoteStoreUtils;
import org.opensearch.index.seqno.RetentionLeaseSyncer;
import org.opensearch.index.shard.IndexEventListener;
import org.opensearch.index.shard.IndexShard;
Expand Down Expand Up @@ -710,7 +711,8 @@ public synchronized IndexShard createShard(
this.indexSettings.getUUID(),
shardId,
this.indexSettings.getRemoteStorePathStrategy(),
this.indexSettings.getRemoteStoreSegmentPathPrefix()
this.indexSettings.getRemoteStoreSegmentPathPrefix(),
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(this.indexSettings.getIndexMetadata())
);
}
// When an instance of Store is created, a shardlock is created which is released on closing the instance of store.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.opensearch.index.remote.RemoteStoreEnums.PathHashAlgorithm;
import org.opensearch.index.remote.RemoteStoreEnums.PathType;
import org.opensearch.indices.RemoteStoreSettings;
import org.opensearch.node.remotestore.RemoteStoreNodeAttribute;
import org.opensearch.repositories.RepositoriesService;
import org.opensearch.repositories.Repository;
import org.opensearch.repositories.RepositoryMissingException;
Expand Down Expand Up @@ -71,4 +72,19 @@ public boolean isTranslogMetadataEnabled() {
&& blobStoreRepository.blobStore().isBlobMetadataEnabled();
}

public boolean isRemoteStoreRepoServerSideEncryptionEnabled() {
BlobStoreRepository segmentRepository, translogRepository;
try {
segmentRepository = (BlobStoreRepository) repositoriesServiceSupplier.get()
.repository(RemoteStoreNodeAttribute.getRemoteStoreSegmentRepo(settings));
translogRepository = (BlobStoreRepository) repositoriesServiceSupplier.get()
.repository(RemoteStoreNodeAttribute.getRemoteStoreTranslogRepo(settings));
} catch (RepositoryMissingException ex) {
throw new IllegalArgumentException("Repository should be created before creating index with remote_store enabled setting", ex);
}
return Version.V_3_4_0.compareTo(minNodeVersionSupplier.get()) <= 0
&& remoteStoreSettings.isClusterServerSideEncryptionEnabled()
&& segmentRepository.isSeverSideEncryptionEnabled()
&& translogRepository.isSeverSideEncryptionEnabled();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ public static Map<String, String> determineRemoteStoreCustomMetadataDuringMigrat
return remoteCustomData;
}

public static boolean isServerSideEncryptionEnabledIndex(IndexMetadata indexMetadata) {
Map<String, String> remoteCustomData = indexMetadata.getCustomData(IndexMetadata.REMOTE_STORE_CUSTOM_KEY);
return remoteCustomData != null && "true".equalsIgnoreCase(remoteCustomData.get(IndexMetadata.REMOTE_STORE_SSE_ENABLED_INDEX_KEY));
}

/**
* Fetches segment and translog repository names from remote store node attributes.
* Returns a blank {@link HashMap} if the cluster does not contain any remote nodes.
Expand Down
28 changes: 25 additions & 3 deletions server/src/main/java/org/opensearch/index/shard/IndexShard.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
import org.opensearch.index.remote.RemoteSegmentStats;
import org.opensearch.index.remote.RemoteStorePathStrategy;
import org.opensearch.index.remote.RemoteStoreStatsTrackerFactory;
import org.opensearch.index.remote.RemoteStoreUtils;
import org.opensearch.index.search.stats.SearchStats;
import org.opensearch.index.search.stats.ShardSearchStats;
import org.opensearch.index.seqno.ReplicationTracker;
Expand Down Expand Up @@ -5297,7 +5298,8 @@ public void deleteTranslogFilesFromRemoteTranslog() throws IOException {
getThreadPool(),
indexSettings.getRemoteStorePathStrategy(),
remoteStoreSettings,
indexSettings().isTranslogMetadataEnabled()
indexSettings().isTranslogMetadataEnabled(),
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexSettings.getIndexMetadata())
);
}

Expand All @@ -5320,7 +5322,8 @@ public void syncTranslogFilesFromRemoteTranslog() throws IOException {
shardId,
indexSettings.getRemoteStorePathStrategy(),
indexSettings().isTranslogMetadataEnabled(),
0
0,
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexSettings.getIndexMetadata())
);
}

Expand All @@ -5330,6 +5333,24 @@ public void syncTranslogFilesFromGivenRemoteTranslog(
RemoteStorePathStrategy remoteStorePathStrategy,
boolean isTranslogMetadataEnabled,
long timestamp
) throws IOException {
this.syncTranslogFilesFromGivenRemoteTranslog(
repository,
shardId,
remoteStorePathStrategy,
isTranslogMetadataEnabled,
timestamp,
false
);
}

public void syncTranslogFilesFromGivenRemoteTranslog(
Repository repository,
ShardId shardId,
RemoteStorePathStrategy remoteStorePathStrategy,
boolean isTranslogMetadataEnabled,
long timestamp,
boolean isServerSideEncryptionEnabled
) throws IOException {
RemoteFsTranslog.download(
repository,
Expand All @@ -5341,7 +5362,8 @@ public void syncTranslogFilesFromGivenRemoteTranslog(
logger,
shouldSeedRemoteStore(),
isTranslogMetadataEnabled,
timestamp
timestamp,
isServerSideEncryptionEnabled
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,9 @@ void recoverFromSnapshotAndRemoteStore(
remoteStoreRepository,
indexUUID,
shardId,
shallowCopyShardMetadata.getRemoteStorePathStrategy()
shallowCopyShardMetadata.getRemoteStorePathStrategy(),
null,
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexShard.indexSettings.getIndexMetadata())
);
RemoteSegmentMetadata remoteSegmentMetadata = sourceRemoteDirectory.initializeToSpecificCommit(
primaryTerm,
Expand Down Expand Up @@ -503,7 +505,9 @@ void recoverShallowSnapshotV2(
remoteSegmentStoreRepository,
prevIndexMetadata.getIndexUUID(),
shardId,
remoteStorePathStrategy
remoteStorePathStrategy,
null,
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(prevIndexMetadata)
);
RemoteSegmentMetadata remoteSegmentMetadata = sourceRemoteDirectory.initializeToSpecificTimestamp(
recoverySource.pinnedTimestamp()
Expand All @@ -523,7 +527,8 @@ void recoverShallowSnapshotV2(
new ShardId(prevIndexMetadata.getIndex(), shardId.id()),
remoteStorePathStrategy,
RemoteStoreUtils.determineTranslogMetadataEnabled(prevIndexMetadata),
recoverySource.pinnedTimestamp()
recoverySource.pinnedTimestamp(),
RemoteStoreUtils.isServerSideEncryptionEnabledIndex(indexShard.indexSettings.getIndexMetadata())
);

assert indexShard.shardRouting.primary() : "only primary shards can recover from store";
Expand Down
Loading
Loading