[KEYCLOAK-18255] - Vault Support in Dist.X
This commit is contained in:
parent
62482eb313
commit
eaa96f6147
38 changed files with 537 additions and 69 deletions
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.keycloak;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
|
@ -154,6 +156,11 @@ public class Config {
|
|||
return new SystemPropertiesScope(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,5 +188,6 @@ public class Config {
|
|||
|
||||
Scope scope(String... scope);
|
||||
|
||||
Set<String> getPropertyNames();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,10 @@
|
|||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-metrics-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-vault-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5-internal</artifactId>
|
||||
|
|
|
@ -556,7 +556,7 @@ class KeycloakProcessor {
|
|||
return false;
|
||||
}
|
||||
if (factory instanceof EnvironmentDependentProviderFactory) {
|
||||
return ((EnvironmentDependentProviderFactory) factory).isSupported();
|
||||
return ((EnvironmentDependentProviderFactory) factory).isSupported(scope);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,3 +4,6 @@ quarkus.banner.enabled=false
|
|||
|
||||
quarkus.resteasy.ignore-application-classes=true
|
||||
quarkus.arc.ignored-split-packages=org.keycloak.*
|
||||
|
||||
# we do not want running testcontainers when running tests in this module
|
||||
quarkus.devservices.enabled=false
|
|
@ -71,6 +71,10 @@
|
|||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-metrics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-vault</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- CLI -->
|
||||
<dependency>
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.keycloak.quarkus.runtime;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getBuiltTimeProperty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.nio.file.Path;
|
||||
|
@ -24,14 +26,12 @@ import java.nio.file.Paths;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.quarkus.runtime.LaunchMode;
|
||||
import io.quarkus.runtime.configuration.ProfileManager;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||
|
||||
public final class Environment {
|
||||
|
||||
|
@ -112,16 +112,6 @@ public final class Environment {
|
|||
return profile;
|
||||
}
|
||||
|
||||
public static Optional<String> getBuiltTimeProperty(String name) {
|
||||
String value = Configuration.getBuiltTimeProperty(name);
|
||||
|
||||
if (value == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(value);
|
||||
}
|
||||
|
||||
public static boolean isDevMode() {
|
||||
if ("dev".equalsIgnoreCase(getProfile())) {
|
||||
return true;
|
||||
|
|
|
@ -20,8 +20,11 @@ package org.keycloak.quarkus.runtime.cli;
|
|||
import static java.util.Arrays.asList;
|
||||
import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.AUTO_BUILD_OPTION;
|
||||
import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfig;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getBuiltTimeProperty;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getRuntimeProperty;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.isBuildTimeProperty;
|
||||
import static org.keycloak.quarkus.runtime.Environment.isDevMode;
|
||||
import static org.keycloak.utils.StringUtil.isNotBlank;
|
||||
import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -70,6 +73,7 @@ public final class Picocli {
|
|||
|
||||
private static final String ARG_SEPARATOR = ";;";
|
||||
public static final String ARG_PREFIX = "--";
|
||||
public static final String ARG_PART_SEPARATOR = "-";
|
||||
public static final char ARG_KEY_VALUE_SEPARATOR = '=';
|
||||
public static final Pattern ARG_SPLIT = Pattern.compile(";;");
|
||||
public static final Pattern ARG_KEY_VALUE_SPLIT = Pattern.compile("=");
|
||||
|
@ -206,7 +210,7 @@ public final class Picocli {
|
|||
|
||||
private static boolean hasConfigChanges() {
|
||||
Optional<String> currentProfile = Optional.ofNullable(Environment.getProfile());
|
||||
Optional<String> persistedProfile = Environment.getBuiltTimeProperty("kc.profile");
|
||||
Optional<String> persistedProfile = getBuiltTimeProperty("kc.profile");
|
||||
|
||||
if (!persistedProfile.orElse("").equals(currentProfile.orElse(""))) {
|
||||
return true;
|
||||
|
@ -218,16 +222,27 @@ public final class Picocli {
|
|||
continue;
|
||||
}
|
||||
|
||||
ConfigValue configValue = getConfig().getConfigValue(propertyName);
|
||||
|
||||
if (configValue == null || configValue.getConfigSourceName() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// try to resolve any property set using profiles
|
||||
if (propertyName.startsWith("%")) {
|
||||
propertyName = propertyName.substring(propertyName.indexOf('.') + 1);
|
||||
}
|
||||
|
||||
String currentValue = Environment.getBuiltTimeProperty(propertyName).orElse(null);
|
||||
String newValue = getConfig().getConfigValue(propertyName).getValue();
|
||||
String persistedValue = getBuiltTimeProperty(propertyName).orElse("");
|
||||
String runtimeValue = getRuntimeProperty(propertyName).orElse(null);
|
||||
|
||||
if (newValue != null && !newValue.equalsIgnoreCase(currentValue)) {
|
||||
// changes to a single property are enough to indicate changes to configuration
|
||||
if (runtimeValue == null && isNotBlank(persistedValue)) {
|
||||
// probably because it was unset
|
||||
return true;
|
||||
}
|
||||
|
||||
// changes to a single property is enough to indicate changes to configuration
|
||||
if (!persistedValue.equals(runtimeValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +330,8 @@ public final class Picocli {
|
|||
String name = ARG_PREFIX + PropertyMappers.toCLIFormat(mapper.getFrom()).substring(3);
|
||||
String description = mapper.getDescription();
|
||||
|
||||
if (description == null || commandSpec.optionsMap().containsKey(name)) {
|
||||
if (description == null || commandSpec.optionsMap().containsKey(name)
|
||||
|| name.endsWith(ARG_PART_SEPARATOR)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -443,4 +459,8 @@ public final class Picocli {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String normalizeKey(String key) {
|
||||
return key.replace('-', '.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfig
|
|||
import static org.keycloak.quarkus.runtime.configuration.Configuration.getPropertyNames;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.canonicalFormat;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.formatValue;
|
||||
import static org.keycloak.quarkus.runtime.Environment.getBuiltTimeProperty;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getBuiltTimeProperty;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
@ -171,6 +171,10 @@ public final class ShowConfig extends AbstractCommand implements Runnable {
|
|||
return;
|
||||
}
|
||||
|
||||
if (configValue.getSourceName() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
spec.commandLine().getOut().printf("\t%s = %s (%s)%n", configValue.getName(), formatValue(configValue.getName(), configValue.getValue()), configValue.getConfigSourceName());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.keycloak.quarkus.runtime.cli.Picocli.ARG_PREFIX;
|
|||
import static org.keycloak.quarkus.runtime.cli.Picocli.ARG_SPLIT;
|
||||
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
|
||||
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_QUARKUS_PREFIX;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getMappedPropertyName;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -32,6 +33,7 @@ import org.jboss.logging.Logger;
|
|||
|
||||
import io.smallrye.config.PropertiesConfigSource;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.Picocli;
|
||||
|
||||
/**
|
||||
* <p>A configuration source for mapping configuration arguments to their corresponding properties so that they can be recognized
|
||||
|
@ -55,25 +57,15 @@ public class ConfigArgsConfigSource extends PropertiesConfigSource {
|
|||
|
||||
@Override
|
||||
public String getValue(String propertyName) {
|
||||
String prefix = null;
|
||||
String value = super.getValue(propertyName.replace('-', '.'));
|
||||
|
||||
// we only care about runtime args passed when executing the CLI, no need to check if the property is prefixed with a profile
|
||||
if (propertyName.startsWith(NS_KEYCLOAK_PREFIX)) {
|
||||
prefix = NS_KEYCLOAK_PREFIX;
|
||||
} else if (propertyName.startsWith(NS_QUARKUS_PREFIX)) {
|
||||
prefix = NS_QUARKUS_PREFIX;
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// we only recognize properties within keycloak and quarkus namespaces
|
||||
if (prefix == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] parts = DOT_SPLIT.split(propertyName.substring(propertyName.indexOf(prefix) + prefix.length()));
|
||||
|
||||
return super.getValue(prefix + String.join("-", parts));
|
||||
}
|
||||
|
||||
private static Map<String, String> parseArgument() {
|
||||
String args = Environment.getConfigArgs();
|
||||
|
||||
|
@ -111,8 +103,10 @@ public class ConfigArgsConfigSource extends PropertiesConfigSource {
|
|||
key = NS_KEYCLOAK_PREFIX + key.substring(2);
|
||||
|
||||
log.tracef("Adding property [%s=%s] from command-line", key, value);
|
||||
|
||||
properties.put(key, value);
|
||||
properties.put(getMappedPropertyName(key), value);
|
||||
// to make lookup easier, we normalize the key
|
||||
properties.put(Picocli.normalizeKey(key), value);
|
||||
}
|
||||
|
||||
return properties;
|
||||
|
|
|
@ -42,6 +42,10 @@ public final class Configuration {
|
|||
public static String getBuiltTimeProperty(String name) {
|
||||
String value = KeycloakConfigSourceProvider.PERSISTED_CONFIG_SOURCE.getValue(name);
|
||||
|
||||
if (value == null) {
|
||||
value = KeycloakConfigSourceProvider.PERSISTED_CONFIG_SOURCE.getValue(PropertyMappers.getMappedPropertyName(name));
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
String profile = Environment.getProfile();
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.quarkus.runtime.configuration;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import org.eclipse.microprofile.config.spi.ConfigSource;
|
||||
|
||||
public class EnvConfigSource implements ConfigSource {
|
||||
|
||||
private final Map<String, String> properties = new TreeMap<>();
|
||||
|
||||
public EnvConfigSource() {
|
||||
for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX.toUpperCase().replace('.', '_'))) {
|
||||
properties.put(PropertyMappers.getMappedPropertyName(key), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
return properties.keySet();
|
||||
}
|
||||
|
||||
public String getValue(final String propertyName) {
|
||||
return System.getProperty(propertyName);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "KcEnvVarConfigSource";
|
||||
}
|
||||
|
||||
public int getOrdinal() {
|
||||
return 350;
|
||||
}
|
||||
}
|
|
@ -52,9 +52,10 @@ public class KeycloakConfigSourceProvider implements ConfigSourceProvider {
|
|||
}
|
||||
|
||||
CONFIG_SOURCES.add(new ConfigArgsConfigSource());
|
||||
CONFIG_SOURCES.add(new SysPropConfigSource());
|
||||
CONFIG_SOURCES.add(new EnvConfigSource());
|
||||
PERSISTED_CONFIG_SOURCE = new PersistedConfigSource(getPersistedConfigFile());
|
||||
CONFIG_SOURCES.add(PERSISTED_CONFIG_SOURCE);
|
||||
CONFIG_SOURCES.add(new SysPropConfigSource());
|
||||
|
||||
Path configFile = getConfigurationFile();
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import io.smallrye.config.PropertiesConfigSource;
|
|||
import static org.keycloak.common.util.StringPropertyReplacer.replaceProperties;
|
||||
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK;
|
||||
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_QUARKUS;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMappers.getMappedPropertyName;
|
||||
|
||||
/**
|
||||
* A configuration source for {@code keycloak.properties}.
|
||||
|
@ -68,7 +69,7 @@ public abstract class KeycloakPropertiesConfigSource extends PropertiesConfigSou
|
|||
|
||||
public static final class InJar extends KeycloakPropertiesConfigSource {
|
||||
public InJar() {
|
||||
super(openStream(), 245);
|
||||
super(openStream(), 250);
|
||||
}
|
||||
|
||||
private static InputStream openStream() {
|
||||
|
@ -93,7 +94,7 @@ public abstract class KeycloakPropertiesConfigSource extends PropertiesConfigSou
|
|||
public static final class InFileSystem extends KeycloakPropertiesConfigSource {
|
||||
|
||||
public InFileSystem(Path path) {
|
||||
super(openStream(path), 255);
|
||||
super(openStream(path), 250);
|
||||
}
|
||||
|
||||
private static InputStream openStream(Path path) {
|
||||
|
@ -113,7 +114,13 @@ public abstract class KeycloakPropertiesConfigSource extends PropertiesConfigSou
|
|||
|
||||
private static Map<String, String> transform(Map<String, String> properties) {
|
||||
Map<String, String> result = new HashMap<>(properties.size());
|
||||
properties.keySet().forEach(k -> result.put(transformKey(k), replaceProperties(properties.get(k))));
|
||||
properties.keySet().forEach(k -> {
|
||||
String key = transformKey(k);
|
||||
String value = replaceProperties(properties.get(k));
|
||||
|
||||
result.put(key, value);
|
||||
result.put(getMappedPropertyName(key), value);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,15 @@
|
|||
|
||||
package org.keycloak.quarkus.runtime.configuration;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.eclipse.microprofile.config.ConfigProvider;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.quarkus.runtime.cli.Picocli;
|
||||
|
||||
public class MicroProfileConfigProvider implements Config.ConfigProvider {
|
||||
|
||||
|
@ -109,6 +114,18 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider {
|
|||
return new MicroProfileScope(ArrayUtils.addAll(this.scope, scope));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
return StreamSupport.stream(config.getPropertyNames().spliterator(), false)
|
||||
.filter(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String key) {
|
||||
return key.startsWith(prefix) || key.startsWith(Picocli.normalizeKey(prefix));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private <T> T getValue(String key, Class<T> clazz, T defaultValue) {
|
||||
return config.getOptionalValue(toDashCase(prefix.concat(".").concat(key)), clazz).orElse(defaultValue);
|
||||
}
|
||||
|
|
|
@ -58,10 +58,6 @@ public class PersistedConfigSource extends PropertiesConfigSource {
|
|||
return value;
|
||||
}
|
||||
|
||||
if (propertyName.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)) {
|
||||
return super.getValue(PropertyMappers.toCLIFormat(propertyName));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,13 @@ public class PropertyMapper {
|
|||
}
|
||||
|
||||
ConfigValue getOrDefault(String name, ConfigSourceInterceptorContext context, ConfigValue current) {
|
||||
String from = this.from;
|
||||
|
||||
if (to != null && to.endsWith(".")) {
|
||||
// in case mapping is based on prefixes instead of full property names
|
||||
from = name.replace(to.substring(0, to.lastIndexOf('.')), from.substring(0, from.lastIndexOf('.')));
|
||||
}
|
||||
|
||||
// try to obtain the value for the property we want to map
|
||||
ConfigValue config = context.proceed(from);
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.keycloak.quarkus.runtime.configuration;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.Environment.getProfileOrDefault;
|
||||
import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfig;
|
||||
import static org.keycloak.quarkus.runtime.configuration.Messages.invalidDatabaseVendor;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMapper.MAPPERS;
|
||||
import static org.keycloak.quarkus.runtime.configuration.PropertyMapper.create;
|
||||
|
@ -26,7 +28,9 @@ import static org.keycloak.quarkus.runtime.integration.QuarkusPlatform.addInitia
|
|||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -34,6 +38,7 @@ import java.util.stream.Collectors;
|
|||
import io.smallrye.config.ConfigSourceInterceptorContext;
|
||||
import io.smallrye.config.ConfigValue;
|
||||
|
||||
import org.eclipse.microprofile.config.spi.ConfigSource;
|
||||
import org.keycloak.quarkus.runtime.storage.database.Database;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
|
||||
|
@ -50,6 +55,7 @@ public final class PropertyMappers {
|
|||
configureClustering();
|
||||
configureHostnameProviderMappers();
|
||||
configureMetrics();
|
||||
configureVault();
|
||||
}
|
||||
|
||||
private static void configureHttpPropertyMappers() {
|
||||
|
@ -164,9 +170,45 @@ public final class PropertyMappers {
|
|||
Arrays.asList(Boolean.TRUE.toString(), Boolean.FALSE.toString()));
|
||||
}
|
||||
|
||||
private static void configureVault() {
|
||||
createBuildTimeProperty("vault.file.path", "kc.spi.vault.files-plaintext.dir", "If set, secrets can be obtained by reading the content of files within the given path.");
|
||||
createBuildTimeProperty("vault.hashicorp.", "quarkus.vault.", "If set, secrets can be obtained from Hashicorp Vault.");
|
||||
createBuildTimeProperty("vault.hashicorp.paths", "kc.spi.vault.hashicorp.paths", "A set of one or more paths that should be used when looking up secrets.");
|
||||
}
|
||||
|
||||
static ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
|
||||
return PropertyMapper.MAPPERS.getOrDefault(name, PropertyMapper.IDENTITY)
|
||||
PropertyMapper mapper = MAPPERS.getOrDefault(name, PropertyMapper.IDENTITY);
|
||||
ConfigValue configValue = mapper
|
||||
.getOrDefault(name, context, context.proceed(name));
|
||||
|
||||
if (configValue == null) {
|
||||
Optional<String> prefixedMapper = getPrefixedMapper(name);
|
||||
|
||||
if (prefixedMapper.isPresent()) {
|
||||
return MAPPERS.get(prefixedMapper.get()).getOrDefault(name, context, configValue);
|
||||
}
|
||||
} else {
|
||||
configValue.withName(mapper.getTo());
|
||||
}
|
||||
|
||||
return configValue;
|
||||
}
|
||||
|
||||
private static Optional<String> getPrefixedMapper(String name) {
|
||||
Optional<String> prefixedMapper = MAPPERS.keySet().stream().filter(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String key) {
|
||||
if (!key.endsWith(".")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String prefix = key.substring(0, key.lastIndexOf('.') - 1);
|
||||
|
||||
return name.startsWith(prefix);
|
||||
}
|
||||
}).findAny();
|
||||
|
||||
return prefixedMapper;
|
||||
}
|
||||
|
||||
public static boolean isBuildTimeProperty(String name) {
|
||||
|
@ -176,8 +218,9 @@ public final class PropertyMappers {
|
|||
}
|
||||
|
||||
return name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)
|
||||
&& PropertyMapper.MAPPERS.entrySet().stream()
|
||||
.anyMatch(entry -> entry.getValue().getFrom().equals(name) && entry.getValue().isBuildTime())
|
||||
&& PropertyMapper.MAPPERS.values().stream()
|
||||
.filter(PropertyMapper::isBuildTime)
|
||||
.anyMatch(mapper -> mapper.getFrom().equals(name) || mapper.getTo().equals(name))
|
||||
&& !"kc.version".equals(name)
|
||||
&& !Environment.CLI_ARGS.equals(name)
|
||||
&& !"kc.home.dir".equals(name)
|
||||
|
@ -215,6 +258,10 @@ public final class PropertyMappers {
|
|||
.filter(entry -> entry.isBuildTime()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Collection<PropertyMapper> getMappers() {
|
||||
return MAPPERS.values();
|
||||
}
|
||||
|
||||
public static String canonicalFormat(String name) {
|
||||
return name.replaceAll("-", "\\.");
|
||||
}
|
||||
|
@ -237,4 +284,58 @@ public final class PropertyMappers {
|
|||
}
|
||||
}).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static String getMappedPropertyName(String key) {
|
||||
for (PropertyMapper mapper : PropertyMappers.getMappers()) {
|
||||
String mappedProperty = mapper.getFrom();
|
||||
List<String> expectedFormats = Arrays.asList(mappedProperty, toCLIFormat(mappedProperty), mappedProperty.toUpperCase().replace('.', '_').replace('-', '_'));
|
||||
|
||||
if (expectedFormats.contains(key)) {
|
||||
// we also need to make sure the target property is available when defined such as when defining alias for provider config (no spi-prefix).
|
||||
return mapper.getTo() == null ? mappedProperty : mapper.getTo();
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static Optional<String> getBuiltTimeProperty(String name) {
|
||||
String value = Configuration.getBuiltTimeProperty(name);
|
||||
|
||||
if (value == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(value);
|
||||
}
|
||||
|
||||
public static Optional<String> getRuntimeProperty(String name) {
|
||||
for (ConfigSource configSource : getConfig().getConfigSources()) {
|
||||
if (PersistedConfigSource.NAME.equals(configSource.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = getValue(configSource, name);
|
||||
|
||||
if (value == null) {
|
||||
value = getValue(configSource, PropertyMappers.getMappedPropertyName(name));
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
return Optional.of(value);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static String getValue(ConfigSource configSource, String name) {
|
||||
String value = configSource.getValue(name);
|
||||
|
||||
if (value == null) {
|
||||
value = configSource.getValue("%".concat(getProfileOrDefault("prod").concat(".").concat(name)));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.quarkus.runtime.vault;
|
||||
|
||||
import static org.keycloak.vault.DefaultVaultRawSecret.forBuffer;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.keycloak.vault.AbstractVaultProvider;
|
||||
import org.keycloak.vault.VaultKeyResolver;
|
||||
import org.keycloak.vault.VaultRawSecret;
|
||||
|
||||
import io.quarkus.vault.VaultKVSecretEngine;
|
||||
|
||||
public class QuarkusVaultProvider extends AbstractVaultProvider {
|
||||
|
||||
private VaultKVSecretEngine secretEngine;
|
||||
private String[] kvPaths;
|
||||
|
||||
public QuarkusVaultProvider(VaultKVSecretEngine secretEngine, String[] kvPaths, String realm, List<VaultKeyResolver> keyResolvers) {
|
||||
super(realm, keyResolvers);
|
||||
this.secretEngine = secretEngine;
|
||||
this.kvPaths = kvPaths;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VaultRawSecret obtainSecretInternal(String key) {
|
||||
if (kvPaths == null) {
|
||||
return forBuffer(Optional.empty());
|
||||
}
|
||||
|
||||
for (String path : kvPaths) {
|
||||
Map<String, String> secrets = secretEngine.readSecret(path);
|
||||
String secret = secrets.get(key);
|
||||
|
||||
if (secret != null) {
|
||||
return forBuffer(Optional.of(StandardCharsets.UTF_8.encode(CharBuffer.wrap(secret))));
|
||||
}
|
||||
}
|
||||
|
||||
return forBuffer(Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.quarkus.runtime.vault;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.vault.AbstractVaultProviderFactory;
|
||||
import org.keycloak.vault.VaultProvider;
|
||||
|
||||
import io.quarkus.arc.Arc;
|
||||
import io.quarkus.arc.InstanceHandle;
|
||||
import io.quarkus.vault.VaultKVSecretEngine;
|
||||
import io.quarkus.vault.runtime.VaultConfigHolder;
|
||||
|
||||
public class QuarkusVaultProviderFactory extends AbstractVaultProviderFactory implements EnvironmentDependentProviderFactory {
|
||||
|
||||
private String[] kvPaths;
|
||||
private VaultKVSecretEngine secretEngine;
|
||||
|
||||
@Override
|
||||
public VaultProvider create(KeycloakSession session) {
|
||||
return new QuarkusVaultProvider(secretEngine, kvPaths, getRealmName(session), super.keyResolvers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
super.init(config);
|
||||
kvPaths = config.getArray("paths");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
InstanceHandle<VaultKVSecretEngine> engineInstance = Arc.container().instance(VaultKVSecretEngine.class);
|
||||
|
||||
if (engineInstance.isAvailable()) {
|
||||
secretEngine = engineInstance.get();
|
||||
}
|
||||
|
||||
InstanceHandle<VaultConfigHolder> configInstance = Arc.container().instance(VaultConfigHolder.class);
|
||||
|
||||
if (!configInstance.isAvailable() || configInstance.get().getVaultBootstrapConfig() == null) {
|
||||
throw new RuntimeException("No configuration defined for hashicorp provider.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "hashicorp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(Config.Scope config) {
|
||||
return !config.getPropertyNames().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
// in quarkus we do not use this method when installing providers
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.quarkus.runtime.vault.QuarkusVaultProviderFactory
|
|
@ -42,6 +42,7 @@ import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
|
|||
import io.quarkus.runtime.configuration.ConfigUtils;
|
||||
import io.smallrye.config.SmallRyeConfigProviderResolver;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.vault.FilesPlainTextVaultProviderFactory;
|
||||
|
||||
public class ConfigurationTest {
|
||||
|
||||
|
@ -175,6 +176,33 @@ public class ConfigurationTest {
|
|||
assertEquals("http://c.jwk.url", initConfig("client-registration", "openid-connect").get("static-jwk-url"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyNamesFromConfig() {
|
||||
System.setProperty(CLI_ARGS, "--spi-client-registration-openid-connect-static-jwk-url=http://c.jwk.url");
|
||||
Config.Scope config = initConfig("client-registration", "openid-connect");
|
||||
assertEquals(1, config.getPropertyNames().size());
|
||||
assertEquals("http://c.jwk.url", config.get("static-jwk-url"));
|
||||
|
||||
System.setProperty(CLI_ARGS, "--vault-file-path=secrets");
|
||||
config = initConfig("vault", FilesPlainTextVaultProviderFactory.PROVIDER_ID);
|
||||
assertEquals(1, config.getPropertyNames().size());
|
||||
assertEquals("secrets", config.get("dir"));
|
||||
|
||||
System.getProperties().remove(CLI_ARGS);
|
||||
System.setProperty("kc.spi.client-registration.openid-connect.static-jwk-url", "http://c.jwk.url");
|
||||
config = initConfig("client-registration", "openid-connect");
|
||||
assertEquals(1, config.getPropertyNames().size());
|
||||
assertEquals("http://c.jwk.url", config.get("static-jwk-url"));
|
||||
|
||||
System.getProperties().remove(CLI_ARGS);
|
||||
System.getProperties().remove("kc.spi.client-registration.openid-connect.static-jwk-url");
|
||||
putEnvVar("KC_SPI_CLIENT_REGISTRATION_OPENID_CONNECT_STATIC_JWK_URL", "http://c.jwk.url/from-env");
|
||||
config = initConfig("client-registration", "openid-connect");
|
||||
assertEquals(1, config.getPropertyNames().size());
|
||||
assertEquals("http://c.jwk.url/from-env", config.get("static-jwk-url"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPropertyMapping() {
|
||||
System.setProperty(CLI_ARGS, "--db=mariadb" + ARG_SEPARATOR + "--db-url=jdbc:mariadb://localhost/keycloak");
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
*/
|
||||
package org.keycloak.component;
|
||||
|
||||
import java.util.Set;
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -114,4 +114,9 @@ public class ComponentModelScope implements Scope {
|
|||
return new ComponentModelScope(origScope.scope(scope), componentConfig, String.join(".", scope) + ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.keycloak.provider;
|
||||
|
||||
import org.keycloak.Config;
|
||||
|
||||
/**
|
||||
* Providers that are only supported in some environments can implement this interface to be able to determine if they
|
||||
* should be available or not.
|
||||
|
@ -27,7 +29,18 @@ public interface EnvironmentDependentProviderFactory {
|
|||
|
||||
/**
|
||||
* @return <code>true</code> if the provider is supported and should be available, <code>false</code> otherwise
|
||||
* @deprecated Prefer overriding/using the {@link #isSupported(Config.Scope)} method.
|
||||
*/
|
||||
boolean isSupported();
|
||||
|
||||
/**
|
||||
* An alternative to {@link #isSupported()} method to check if the provider is supported based on the
|
||||
* provider configuration.
|
||||
*
|
||||
* @param config the provider configuration
|
||||
* @return {@code true} if the provider is supported. Otherwise, {@code false}.
|
||||
*/
|
||||
default boolean isSupported(Config.Scope config) {
|
||||
return isSupported();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.Config;
|
|||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -183,6 +184,11 @@ public class JsonConfigProvider implements Config.ConfigProvider {
|
|||
return new JsonScope(getNode(config, path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.keycloak.services.DefaultKeycloakSessionFactory;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link FilesPlainTextVaultProviderFactory}.
|
||||
*
|
||||
|
@ -129,6 +131,11 @@ public class PlainTextVaultProviderFactoryTest {
|
|||
public Config.Scope scope(String... scope) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -113,6 +113,25 @@
|
|||
<overwrite>true</overwrite>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-vault-secrets</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${auth.server.home}/secrets</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${common.resources}/vault</directory>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<overwrite>true</overwrite>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>add-extending-theme</id>
|
||||
<phase>process-resources</phase>
|
||||
|
|
|
@ -41,3 +41,6 @@ spi.events-store.jpa.max-detail-length=2000
|
|||
|
||||
# set known protocol ports for basicsamltest
|
||||
spi.login-protocol.saml.known-protocols=http=8180,https=8543
|
||||
|
||||
# File-Based Vault
|
||||
vault.file.path=${kc.home.dir}secrets
|
||||
|
|
|
@ -568,7 +568,7 @@ public class AuthServerTestEnricher {
|
|||
}
|
||||
}
|
||||
|
||||
if (!isAuthServerQuarkus() && event.getTestClass().isAnnotationPresent(EnableVault.class)) {
|
||||
if (event.getTestClass().isAnnotationPresent(EnableVault.class)) {
|
||||
VaultUtils.enableVault(suiteContext, event.getTestClass().getAnnotation(EnableVault.class).providerId());
|
||||
wasUpdated = true;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,9 @@ public class VaultTestExecutionDecider implements TestExecutionDecider {
|
|||
if (suiteContext != null && suiteContext.getAuthServerInfo() != null && suiteContext.getAuthServerInfo().isUndertow()) {
|
||||
return ExecutionDecision.dontExecute("@EnableVault with Elytron credential store provider not supported on Undertow, skipping");
|
||||
}
|
||||
if (suiteContext != null && suiteContext.getAuthServerInfo() != null && suiteContext.getAuthServerInfo().isQuarkus()) {
|
||||
return ExecutionDecision.dontExecute("@EnableVault with Elytron credential store provider not supported on Quarkus, skipping");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ExecutionDecision.execute();
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.util;
|
|||
|
||||
|
||||
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.ContainerInfo;
|
||||
import org.keycloak.testsuite.arquillian.SuiteContext;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableVault;
|
||||
import org.wildfly.extras.creaper.core.online.CliException;
|
||||
|
@ -34,9 +35,11 @@ import java.util.concurrent.TimeoutException;
|
|||
public class VaultUtils {
|
||||
|
||||
public static void enableVault(SuiteContext suiteContext, EnableVault.PROVIDER_ID provider) throws IOException, CliException, TimeoutException, InterruptedException {
|
||||
if (suiteContext.getAuthServerInfo().isUndertow()) {
|
||||
ContainerInfo serverInfo = suiteContext.getAuthServerInfo();
|
||||
|
||||
if (serverInfo.isUndertow()) {
|
||||
System.setProperty("keycloak.vault." + provider.getName() + ".provider.enabled", "true");
|
||||
} else {
|
||||
} else if (serverInfo.isJBossBased()) {
|
||||
OnlineManagementClient client = AuthServerTestEnricher.getManagementClient();
|
||||
// configure the selected provider and set it as the default vault provider.
|
||||
client.execute("/subsystem=keycloak-server/spi=vault/:add(default-provider=" + provider.getName() + ")");
|
||||
|
@ -48,9 +51,11 @@ public class VaultUtils {
|
|||
}
|
||||
|
||||
public static void disableVault(SuiteContext suiteContext, EnableVault.PROVIDER_ID provider) throws IOException, CliException, TimeoutException, InterruptedException {
|
||||
if (suiteContext.getAuthServerInfo().isUndertow() || suiteContext.getAuthServerInfo().isQuarkus()) {
|
||||
ContainerInfo serverInfo = suiteContext.getAuthServerInfo();
|
||||
|
||||
if (serverInfo.isUndertow()) {
|
||||
System.setProperty("keycloak.vault." + provider.getName() + ".provider.enabled", "false");
|
||||
} else {
|
||||
} else if (serverInfo.isJBossBased()) {
|
||||
OnlineManagementClient client = AuthServerTestEnricher.getManagementClient();
|
||||
for (String command : provider.getCliRemovalCommands()) {
|
||||
client.execute(command);
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.A
|
|||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@EnableVault
|
||||
@AuthServerContainerExclude({AuthServer.REMOTE, AuthServer.QUARKUS})
|
||||
@AuthServerContainerExclude(AuthServer.REMOTE)
|
||||
public class UserFederationLdapConnectionTest extends AbstractAdminTest {
|
||||
|
||||
@ClassRule
|
||||
|
|
|
@ -39,13 +39,12 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.QUARKUS;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
@AuthServerContainerExclude({REMOTE})
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public class ClientSearchTest extends AbstractClientTest {
|
||||
@ArquillianResource
|
||||
protected ContainerController controller;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.testsuite.broker;
|
||||
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableVault;
|
||||
|
||||
|
@ -7,7 +9,7 @@ import org.keycloak.testsuite.arquillian.annotation.EnableVault;
|
|||
* @author Martin Kanis <mkanis@redhat.com>
|
||||
*/
|
||||
@EnableVault
|
||||
@AuthServerContainerExclude({AuthServerContainerExclude.AuthServer.QUARKUS, AuthServerContainerExclude.AuthServer.REMOTE})
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public class KcOidcBrokerVaultTest extends AbstractBrokerTest {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -50,8 +50,7 @@ import java.util.List;
|
|||
|
||||
import java.util.Objects;
|
||||
import org.junit.Assume;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
/**
|
||||
* Test user logins utilizing various LDAP authentication methods and different LDAP connection encryption mechanisms.
|
||||
|
@ -227,7 +226,7 @@ public class LDAPUserLoginTest extends AbstractLDAPTest {
|
|||
// Test variant: Bind credential set to vault
|
||||
@Test
|
||||
@LDAPConnectionParameters(bindCredential=LDAPConnectionParameters.BindCredential.VAULT, bindType=LDAPConnectionParameters.BindType.SIMPLE, encryption=LDAPConnectionParameters.Encryption.NONE)
|
||||
@AuthServerContainerExclude(value = {AuthServerContainerExclude.AuthServer.QUARKUS, AuthServerContainerExclude.AuthServer.REMOTE}, details =
|
||||
@AuthServerContainerExclude(value = REMOTE, details =
|
||||
"java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx")
|
||||
public void loginLDAPUserCredentialVaultAuthenticationSimpleEncryptionNone() {
|
||||
verifyConnectionUrlProtocolPrefix("ldap://");
|
||||
|
@ -247,7 +246,7 @@ public class LDAPUserLoginTest extends AbstractLDAPTest {
|
|||
// Test variant: Bind credential set to vault
|
||||
@Test
|
||||
@LDAPConnectionParameters(bindCredential=LDAPConnectionParameters.BindCredential.VAULT, bindType=LDAPConnectionParameters.BindType.SIMPLE, encryption=LDAPConnectionParameters.Encryption.SSL)
|
||||
@AuthServerContainerExclude(value = {AuthServerContainerExclude.AuthServer.QUARKUS, AuthServerContainerExclude.AuthServer.REMOTE}, details =
|
||||
@AuthServerContainerExclude(value = REMOTE, details =
|
||||
"java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx")
|
||||
public void loginLDAPUserCredentialVaultAuthenticationSimpleEncryptionSSL() {
|
||||
verifyConnectionUrlProtocolPrefix("ldaps://");
|
||||
|
@ -267,7 +266,7 @@ public class LDAPUserLoginTest extends AbstractLDAPTest {
|
|||
// Test variant: Bind credential set to vault
|
||||
@Test
|
||||
@LDAPConnectionParameters(bindCredential=LDAPConnectionParameters.BindCredential.VAULT, bindType=LDAPConnectionParameters.BindType.SIMPLE, encryption=LDAPConnectionParameters.Encryption.STARTTLS)
|
||||
@AuthServerContainerExclude(value = {AuthServerContainerExclude.AuthServer.QUARKUS, AuthServerContainerExclude.AuthServer.REMOTE}, details =
|
||||
@AuthServerContainerExclude(value = REMOTE, details =
|
||||
"java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx")
|
||||
public void loginLDAPUserCredentialVaultAuthenticationSimpleEncryptionStartTLS() {
|
||||
verifyConnectionUrlProtocolPrefix("ldap://");
|
||||
|
|
|
@ -9,12 +9,13 @@ import org.keycloak.testsuite.util.LDAPTestConfiguration;
|
|||
import java.util.Map;
|
||||
|
||||
import static org.keycloak.models.LDAPConstants.BIND_CREDENTIAL;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
@EnableVault
|
||||
@AuthServerContainerExclude(value = {AuthServerContainerExclude.AuthServer.QUARKUS, AuthServerContainerExclude.AuthServer.REMOTE}, details = "java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx")
|
||||
@AuthServerContainerExclude(value = REMOTE, details = "java.io.NotSerializableException: com.sun.jndi.ldap.LdapCtx")
|
||||
public class LDAPVaultCredentialsTest extends LDAPSyncTest {
|
||||
|
||||
private static final String VAULT_EXPRESSION = "${vault.ldap_bindCredential}";
|
||||
|
|
|
@ -60,7 +60,6 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_PORT;
|
||||
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SCHEME;
|
||||
import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.QUARKUS;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
@AuthServerContainerExclude({REMOTE})
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.keycloak.vault.VaultTranscriber;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.QUARKUS;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +41,7 @@ import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerEx
|
|||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
@EnableVault
|
||||
@AuthServerContainerExclude({REMOTE, QUARKUS})
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public class KeycloakVaultTest extends AbstractKeycloakTest {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.security.Security;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
@ -349,6 +350,11 @@ public class ElytronCSKeyStoreProviderTest {
|
|||
public Config.Scope scope(String... scope) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPropertyNames() {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
static class SecretContains extends TypeSafeMatcher<VaultRawSecret> {
|
||||
|
|
Loading…
Reference in a new issue