Skip to content

Commit

Permalink
Migration to affix settings
Browse files Browse the repository at this point in the history
- Load of client settings as Map
- EncryptionKeyProvider now creates/recreates together with client
  • Loading branch information
willyborankin committed Feb 13, 2022
1 parent 61a3d5f commit 7997479
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@
import java.io.UncheckedIOException;
import java.security.Security;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.opensearch.cluster.metadata.RepositoryMetadata;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.xcontent.NamedXContentRegistry;
import org.opensearch.env.Environment;
Expand All @@ -46,9 +43,9 @@ public abstract class AbstractRepositoryPlugin<C, S extends CommonSettings.Clien

private final String repositoryType;

private final RepositorySettingsProvider<C, S> repositorySettingsProvider;
private final String repositorySettingsPrefix;

private final Set<String> pluginSettingKeys;
private final RepositorySettingsProvider<C, S> repositorySettingsProvider;

static {
try {
Expand All @@ -59,11 +56,12 @@ public abstract class AbstractRepositoryPlugin<C, S extends CommonSettings.Clien
}

protected AbstractRepositoryPlugin(final String repositoryType,
final String repositorySettingsPrefix,
final Settings settings,
final RepositorySettingsProvider<C, S> repositorySettingsProvider) {
this.repositoryType = repositoryType;
this.repositorySettingsPrefix = repositorySettingsPrefix;
this.repositorySettingsProvider = repositorySettingsProvider;
this.pluginSettingKeys = getSettings().stream().map(Setting::getKey).collect(Collectors.toSet());
reload(settings);
}

Expand All @@ -86,10 +84,9 @@ private org.opensearch.repositories.blobstore.BlobStoreRepository createReposito
@Override
public void reload(final Settings settings) {
try {
final var pluginKeys = settings.filter(pluginSettingKeys::contains);
if (!pluginKeys.isEmpty()) {
if (!settings.getGroups(repositorySettingsPrefix).isEmpty()) {
LOGGER.info("Reload settings for repository type: {}", repositoryType);
repositorySettingsProvider.reload(pluginKeys);
repositorySettingsProvider.reload(settings);
}
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
import java.io.IOException;
import java.util.Objects;

import org.opensearch.common.collect.Tuple;
import org.opensearch.common.settings.Settings;

import io.aiven.elasticsearch.repositories.security.EncryptionKeyProvider;

public abstract class ClientProvider<C, S extends CommonSettings.ClientSettings> implements Closeable {

private final Object lock = new Object();
Expand All @@ -30,18 +33,26 @@ public abstract class ClientProvider<C, S extends CommonSettings.ClientSettings>

protected volatile C client;

public C buildClientIfNeeded(final S clientSettings, final Settings repositorySettings) throws IOException {
private volatile EncryptionKeyProvider encryptionKeyProvider;

public Tuple<EncryptionKeyProvider, C> buildClientIfNeeded(
final S clientSettings,
final Settings repositorySettings) throws IOException {
synchronized (lock) {
if (Objects.isNull(client)) {
client = buildClient(clientSettings, repositorySettings);
encryptionKeyProvider =
EncryptionKeyProvider.of(clientSettings.publicKey(), clientSettings.privateKey());
previousRepositorySettings = repositorySettings;
} else if (!previousRepositorySettings.equals(repositorySettings)) {
closeClient();
encryptionKeyProvider =
EncryptionKeyProvider.of(clientSettings.publicKey(), clientSettings.privateKey());
client = buildClient(clientSettings, repositorySettings);
previousRepositorySettings = repositorySettings;
}
}
return client;
return Tuple.tuple(encryptionKeyProvider, client);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,46 @@ public interface CommonSettings {

interface ClientSettings {

String AIVEN_PREFIX = "aiven";

static String withPrefix(final String key) {
return String.format("%s.%s", AIVEN_PREFIX, key);
}

static <T> void checkSettings(final Setting<T> setting, Settings keystoreSettings) {
if (!setting.exists(keystoreSettings)) {
throw new IllegalArgumentException("Settings with name " + setting.getKey() + " hasn't been set");
String AIVEN_PREFIX = "aiven.";

static <T> void checkSettings(
final Setting.AffixSetting<T> setting,
String clientName,
Settings keystoreSettings) {
if (!setting.getConcreteSettingForNamespace(clientName).exists(keystoreSettings)) {
throw new IllegalArgumentException("Settings with name "
+ setting.getConcreteSettingForNamespace(clientName).getKey()
+ " hasn't been set");
}
}

static byte[] readInputStream(final Setting<InputStream> keySetting,
final Settings keystoreSettings) throws IOException {
try (final var in = keySetting.get(keystoreSettings)) {
static byte[] readInputStream(InputStream keyIn) throws IOException {
try (final var in = keyIn) {
return in.readAllBytes();
}
}

static <T> T getConfigValue(Settings settings, String clientName, Setting.AffixSetting<T> clientSetting) {
final Setting<T> concreteSetting = clientSetting.getConcreteSettingForNamespace(clientName);
return concreteSetting.get(settings);
}

byte[] publicKey();

byte[] privateKey();

}

interface RepositorySettings {

Setting<String> CLIENT_NAME =
Setting.simpleString(
"client",
"default",
Setting.Property.NodeScope,
Setting.Property.Dynamic
);

Setting<String> BASE_PATH =
Setting.simpleString(
"base_path",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,36 @@ public abstract class RepositoryStorageIOProvider<C, S extends CommonSettings.Cl

public static final String REPOSITORY_METADATA_FILE_NAME = "repository_metadata.json";

private final S clientSettings;
private final Map<String, S> clientSettings;

private SecretKey encryptionKey;

private final EncryptionKeyProvider encryptionKeyProvider;

private final ClientProvider<C, S> clientProvider;

public RepositoryStorageIOProvider(final ClientProvider<C, S> clientProvider,
final S clientSettings,
final EncryptionKeyProvider encryptionKeyProvider) {
public RepositoryStorageIOProvider(final ClientProvider<C, S> clientProvider, final Map<String, S> clientSettings) {
this.clientProvider = clientProvider;
this.clientSettings = clientSettings;
this.encryptionKeyProvider = encryptionKeyProvider;
}

public StorageIO createStorageIO(final String basePath, final Settings repositorySettings) throws IOException {
final var bufferSize = Math.toIntExact(BUFFER_SIZE_SETTING.get(repositorySettings).getBytes());
final var client =
final var encProviderAndClient =
Permissions.doPrivileged(() -> {
final var c = clientProvider.buildClientIfNeeded(clientSettings, repositorySettings);
createOrRestoreEncryptionKey(c, basePath, repositorySettings);
final String clientName = CLIENT_NAME.get(repositorySettings);
final var c =
clientProvider.buildClientIfNeeded(clientSettings.get(clientName), repositorySettings);
createOrRestoreEncryptionKey(c.v2(), c.v1(), basePath, repositorySettings);
return c;
});
return createStorageIOFor(client, repositorySettings, new CryptoIOProvider(encryptionKey, bufferSize));
return createStorageIOFor(
encProviderAndClient.v2(),
repositorySettings,
new CryptoIOProvider(encryptionKey, bufferSize)
);
}

private void createOrRestoreEncryptionKey(final C client,
final EncryptionKeyProvider encryptionKeyProvider,
final String basePath,
final Settings repositorySettings) throws IOException {
if (Objects.isNull(encryptionKey)) {
Expand Down

0 comments on commit 7997479

Please sign in to comment.