fix: always replacing placeholders (#31871)
closes: #31625 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
4f03c3bf47
commit
ea3937f37c
6 changed files with 49 additions and 53 deletions
|
@ -101,12 +101,7 @@ public final class StringPropertyReplacer
|
|||
if (props == null) {
|
||||
return replaceProperties(string, (PropertyResolver) null);
|
||||
}
|
||||
return replaceProperties(string, new PropertyResolver() {
|
||||
@Override
|
||||
public String resolve(String property) {
|
||||
return props.getProperty(property);
|
||||
}
|
||||
});
|
||||
return replaceProperties(string, props::getProperty);
|
||||
}
|
||||
|
||||
public static String replaceProperties(final String string, PropertyResolver resolver)
|
||||
|
@ -249,29 +244,6 @@ public final class StringPropertyReplacer
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to resolve a "key" from the provided properties by
|
||||
* checking if it is actually a "key1,key2", in which case
|
||||
* try first "key1", then "key2". If all fails, return null.
|
||||
*
|
||||
* It also accepts "key1," and ",key2".
|
||||
*
|
||||
* @param key the key to resolve
|
||||
* @param props the properties to use
|
||||
* @return the resolved key or null
|
||||
*/
|
||||
private static String resolveCompositeKey(String key, final Properties props) {
|
||||
if (props == null) {
|
||||
return resolveCompositeKey(key, (PropertyResolver) null);
|
||||
}
|
||||
return resolveCompositeKey(key, new PropertyResolver() {
|
||||
@Override
|
||||
public String resolve(String property) {
|
||||
return props.getProperty(property);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String resolveCompositeKey(String key, PropertyResolver resolver)
|
||||
{
|
||||
String value = null;
|
||||
|
|
|
@ -133,3 +133,9 @@ when exporting a realm.
|
|||
|
||||
To obtain the query the identity providers in a realm, prefer using the `/realms/{realm}/identity-provider/instances` endpoint.
|
||||
This endpoint supports filters and pagination.
|
||||
|
||||
= CLI import placeholder replacement
|
||||
|
||||
The CLI command `kc.[sh|bat] import` now has placeholder replacement enabled. Previously placeholder replacement was only enabled for realm import at startup.
|
||||
|
||||
If you wish to disable placeholder replacement for the `import` command, add the system property `-Dkeycloak.migration.replace-placeholders=false`
|
||||
|
|
|
@ -94,6 +94,22 @@ To import a realm previously exported in a single file, you can use the `--file
|
|||
|
||||
<@kc.import parameters="--file <file>"/>
|
||||
|
||||
== Using Environment Variables within the Realm Configuration Files
|
||||
|
||||
You are able to use placeholders to resolve values from environment variables for any realm configuration.
|
||||
|
||||
.Realm configuration using placeholders
|
||||
[source, bash]
|
||||
----
|
||||
{
|
||||
"realm": "${r"${MY_REALM_NAME}"}",
|
||||
"enabled": true,
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
In the example above, the value set to the `MY_REALM_NAME` environment variable is going to be used to set the `realm` property.
|
||||
|
||||
== Importing a Realm during Startup
|
||||
|
||||
You are also able to import realms when the server is starting by using the `--import-realm` option.
|
||||
|
@ -111,22 +127,6 @@ To re-create realms you should explicitly run the `import` command prior to star
|
|||
|
||||
Importing the `master` realm is not supported because as it is a very sensitive operation.
|
||||
|
||||
=== Using Environment Variables within the Realm Configuration Files
|
||||
|
||||
When importing a realm at startup, you are able to use placeholders to resolve values from environment variables for any realm configuration.
|
||||
|
||||
.Realm configuration using placeholders
|
||||
[source, bash]
|
||||
----
|
||||
{
|
||||
"realm": "${r"${MY_REALM_NAME}"}",
|
||||
"enabled": true,
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
In the example above, the value set to the `MY_REALM_NAME` environment variable is going to be used to set the `realm` property.
|
||||
|
||||
== Importing and Exporting by using the Admin Console
|
||||
|
||||
You can also import and export a realm using the Admin Console. This functionality is
|
||||
|
|
|
@ -149,10 +149,8 @@ public class KeycloakRealmImportJobDependentResource extends KubernetesDependent
|
|||
|
||||
var runBuild = !keycloakContainer.getArgs().contains(KeycloakDeploymentDependentResource.OPTIMIZED_ARG) ? "/opt/keycloak/bin/kc.sh --verbose build && " : "";
|
||||
|
||||
var replaceOption = (replacePlaceholders) ? " -Dkeycloak.migration.replace-placeholders=true": "";
|
||||
|
||||
var commandArgs = List.of("-c",
|
||||
runBuild + "/opt/keycloak/bin/kc.sh" + replaceOption + " --verbose import --optimized --file='" + importMntPath + keycloakRealmImport.getRealmName() + "-realm.json' " + override);
|
||||
runBuild + "/opt/keycloak/bin/kc.sh --verbose import --optimized --file='" + importMntPath + keycloakRealmImport.getRealmName() + "-realm.json' " + override);
|
||||
|
||||
keycloakContainer.setCommand(command);
|
||||
keycloakContainer.setArgs(commandArgs);
|
||||
|
|
|
@ -35,7 +35,10 @@ public final class Import extends AbstractNonServerCommand implements Runnable {
|
|||
|
||||
@Override
|
||||
protected void doBeforeRun() {
|
||||
System.setProperty(ExportImportConfig.ACTION, ACTION_IMPORT);
|
||||
if (System.getProperty(ExportImportConfig.REPLACE_PLACEHOLDERS) == null) {
|
||||
ExportImportConfig.setReplacePlaceholders(true);
|
||||
}
|
||||
ExportImportConfig.setAction(ACTION_IMPORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,28 +17,45 @@
|
|||
|
||||
package org.keycloak.it.cli.dist;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
@DistributionTest
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class ImportDistTest {
|
||||
|
||||
@Test
|
||||
void testImport(KeycloakDistribution dist) {
|
||||
void testImport(KeycloakDistribution dist) throws IOException {
|
||||
CLIResult cliResult = dist.run("build");
|
||||
|
||||
cliResult = dist.run("export", "--realm=master", "--dir=.");
|
||||
File dir = new File("target");
|
||||
|
||||
cliResult = dist.run("export", "--realm=master", "--dir=" + dir.getAbsolutePath());
|
||||
cliResult.assertMessage("Export of realm 'master' requested.");
|
||||
cliResult.assertMessage("Export finished successfully");
|
||||
|
||||
cliResult = dist.run("import", "--dir=.");
|
||||
// add a placeholder into the realm
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
File file = new File(dir, "master-realm.json");
|
||||
ObjectNode node = (ObjectNode)mapper.readTree(file);
|
||||
node.put("enabled", "${REALM_ENABLED}");
|
||||
mapper.writer().writeValue(file, node);
|
||||
|
||||
dist.setEnvVar("REALM_ENABLED", "true");
|
||||
cliResult = dist.run("import", "--dir=" + dir.getAbsolutePath());
|
||||
cliResult.assertMessage("Realm 'master' imported");
|
||||
cliResult.assertMessage("Import finished successfully");
|
||||
cliResult.assertNoMessage("Changes detected in configuration");
|
||||
|
|
Loading…
Reference in a new issue