Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Feb 8, 2024
2 parents b83016c + 6ceb064 commit d021652
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import com.evolveum.midpoint.prism.crypto.SecretsProvider;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SecretsProviderType;

public abstract class SecretsProviderImpl<T extends SecretsProviderType> implements SecretsProvider {
public abstract class SecretsProviderImpl<T extends SecretsProviderType> implements SecretsProvider<T> {

private static final String[] EMPTY_DEPENDENCIES = new String[0];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@

package com.evolveum.midpoint.common.secrets;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;

import com.evolveum.midpoint.prism.crypto.SecretsProvider;
import com.evolveum.midpoint.prism.crypto.SecretsResolver;
import com.evolveum.midpoint.util.DependencyGraph;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
Expand All @@ -32,7 +31,7 @@ public class SecretsProviderManager {

private static final Trace LOGGER = TraceManager.getTrace(SecretsProviderManager.class);

private static final Map<Class<? extends SecretsProviderType>, Class<? extends SecretsProvider>> PROVIDER_TYPES =
private static final Map<Class<? extends SecretsProviderType>, Class<? extends SecretsProvider<? extends SecretsProviderType>>> PROVIDER_TYPES =
Map.ofEntries(
Map.entry(DockerSecretsProviderType.class, DockerSecretsProvider.class),
Map.entry(PropertiesSecretsProviderType.class, PropertiesSecretsProvider.class),
Expand All @@ -44,31 +43,46 @@ public synchronized void configure(SecretsResolver consumer, SecretsProvidersTyp
configuration = new SecretsProvidersType();
}

Map<String, SecretsProvider> existingProviders = consumer.getSecretsProviders().stream()
Map<String, SecretsProvider<?>> existingProviders = consumer.getSecretsProviders().stream()
.collect(Collectors.toMap(SecretsProvider::getIdentifier, p -> p));

LOGGER.debug("Existing providers: {}", existingProviders.keySet());

List<SecretsProviderType> configurations = new ArrayList<>();
configurations.add(configuration.getEnvironmentVariablesSecretsProvider());
configurations.add(configuration.getDockerSecretsProvider());
configurations.addAll(configuration.getKubernetesSecretsProvider());
configurations.addAll(configuration.getPropertiesSecretsProvider());
configurations.addAll(configuration.getCustomSecretsProvider());

List<SecretsProvider> newProviders = configurations.stream()
Map<String, SecretsProvider<?>> newProviders = configurations.stream()
.map(c -> createProvider(c))
.filter(p -> p != null)
.toList();
.collect(Collectors.toMap(SecretsProvider::getIdentifier, p -> p));

LOGGER.debug("Preparing new providers: {}", newProviders.keySet());

Map<String, Collection<String>> dependencies = newProviders.values().stream()
.collect(Collectors.toMap(
p -> p.getIdentifier(),
p -> Arrays.asList(p.getDependencies())));

List<String> sorted = DependencyGraph.ofMap(dependencies).getSortedItems();

// todo sort based on dependencies
LOGGER.debug("Sorted providers by dependencies: {}", sorted);

for (SecretsProvider provider : newProviders) {
for (String identifier : sorted) {
LOGGER.trace("Initializing secrets provider: {}", identifier);

SecretsProvider<?> provider = newProviders.get(identifier);
provider.initialize();

LOGGER.trace("Adding secrets provider: {} to resolver", identifier);
consumer.addSecretsProvider(provider);
existingProviders.remove(provider.getIdentifier());
}

// we'll just clear existing providers
LOGGER.debug("Removing remaining old providers: {}", existingProviders.keySet());
existingProviders.values().forEach(p -> destroyProvider(consumer, p));
}

Expand All @@ -91,31 +105,33 @@ public Map<String, DisplayType> getSecretsProviderDescriptions(SecretsResolver c
}));
}

private void destroyProvider(SecretsResolver consumer, SecretsProvider provider) {
private void destroyProvider(SecretsResolver consumer, SecretsProvider<?> provider) {
try {
LOGGER.trace("Removing secrets provider: {} from resolver", provider.getIdentifier());
consumer.removeSecretsProvider(provider);

LOGGER.trace("Destroying secrets provider: {}", provider.getIdentifier());
provider.destroy();
} catch (Exception ex) {
throw new SystemException("Couldn't destroy secrets provider: " + provider.getIdentifier(), ex);
}
}

@SuppressWarnings("unchecked")
private <C extends SecretsProviderType> SecretsProvider createProvider(C configuration) {
private <C extends SecretsProviderType> SecretsProvider<?> createProvider(C configuration) {
if (configuration == null) {
return null;
}

Class<? extends SecretsProvider> providerClass;
Class<? extends SecretsProvider<?>> providerClass;
if (configuration instanceof CustomSecretsProviderType custom) {
String className = custom.getClassName();
if (className == null) {
throw new SystemException("No class name specified for custom secrets provider");
}

try {
providerClass = (Class<? extends SecretsProvider>) Class.forName(className);
providerClass = (Class<? extends SecretsProvider<?>>) Class.forName(className);
} catch (Exception ex) {
throw new SystemException("Couldn't find custom secrets provider class: " + className, ex);
}
Expand All @@ -129,11 +145,9 @@ private <C extends SecretsProviderType> SecretsProvider createProvider(C configu
}

try {
SecretsProvider provider = providerClass
return providerClass
.getConstructor(configuration.getClass())
.newInstance(configuration);

return provider;
} catch (Exception ex) {
throw new SystemException(
"Couldn't create secrets provider instance for configuration of type: " + configuration.getClass(), ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,36 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.evolveum.midpoint.prism.crypto.SecretsResolver;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.ProtectedData;
import com.evolveum.midpoint.prism.crypto.SecretsProvider;
import com.evolveum.midpoint.prism.crypto.SecretsResolver;
import com.evolveum.midpoint.prism.impl.crypto.KeyStoreBasedProtectorImpl;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.prism.xml.ns._public.types_3.ExternalDataType;

import org.jetbrains.annotations.NotNull;

/**
* TODO better name (also for factory)
*/
public class ConfigurableProtector extends KeyStoreBasedProtectorImpl implements SecretsResolver {

private final Map<String, SecretsProvider> providers = new ConcurrentHashMap<>();
private final Map<String, SecretsProvider<?>> providers = new ConcurrentHashMap<>();

@Override
public void addSecretsProvider(@NotNull SecretsProvider provider) {
public void addSecretsProvider(@NotNull SecretsProvider<?> provider) {
providers.put(provider.getIdentifier(), provider);
}

@Override
public void removeSecretsProvider(@NotNull SecretsProvider provider) {
public void removeSecretsProvider(@NotNull SecretsProvider<?> provider) {
providers.remove(provider.getIdentifier());
}

@NotNull
@Override
public List<SecretsProvider> getSecretsProviders() {
public List<SecretsProvider<?>> getSecretsProviders() {
return List.copyOf(providers.values());
}

Expand Down Expand Up @@ -89,7 +89,7 @@ private <T> T resolveExternalData(ExternalDataType external, Class<T> type) thro
throw new EncryptionException("No key specified for provider " + provider);
}

SecretsProvider secretsProvider = providers.get(provider);
SecretsProvider<?> secretsProvider = providers.get(provider);
if (secretsProvider == null) {
throw new EncryptionException("No secrets provider with identifier " + provider + " found");
}
Expand Down

0 comments on commit d021652

Please sign in to comment.