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) {
|
if (props == null) {
|
||||||
return replaceProperties(string, (PropertyResolver) null);
|
return replaceProperties(string, (PropertyResolver) null);
|
||||||
}
|
}
|
||||||
return replaceProperties(string, new PropertyResolver() {
|
return replaceProperties(string, props::getProperty);
|
||||||
@Override
|
|
||||||
public String resolve(String property) {
|
|
||||||
return props.getProperty(property);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String replaceProperties(final String string, PropertyResolver resolver)
|
public static String replaceProperties(final String string, PropertyResolver resolver)
|
||||||
|
@ -249,29 +244,6 @@ public final class StringPropertyReplacer
|
||||||
return buffer.toString();
|
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)
|
private static String resolveCompositeKey(String key, PropertyResolver resolver)
|
||||||
{
|
{
|
||||||
String value = null;
|
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.
|
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.
|
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>"/>
|
<@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
|
== Importing a Realm during Startup
|
||||||
|
|
||||||
You are also able to import realms when the server is starting by using the `--import-realm` option.
|
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.
|
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
|
== Importing and Exporting by using the Admin Console
|
||||||
|
|
||||||
You can also import and export a realm using the Admin Console. This functionality is
|
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 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",
|
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.setCommand(command);
|
||||||
keycloakContainer.setArgs(commandArgs);
|
keycloakContainer.setArgs(commandArgs);
|
||||||
|
|
|
@ -35,7 +35,10 @@ public final class Import extends AbstractNonServerCommand implements Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doBeforeRun() {
|
protected void doBeforeRun() {
|
||||||
System.setProperty(ExportImportConfig.ACTION, ACTION_IMPORT);
|
if (System.getProperty(ExportImportConfig.REPLACE_PLACEHOLDERS) == null) {
|
||||||
|
ExportImportConfig.setReplacePlaceholders(true);
|
||||||
|
}
|
||||||
|
ExportImportConfig.setAction(ACTION_IMPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,28 +17,45 @@
|
||||||
|
|
||||||
package org.keycloak.it.cli.dist;
|
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.MethodOrderer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||||
import org.keycloak.it.utils.KeycloakDistribution;
|
import org.keycloak.it.utils.KeycloakDistribution;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
@DistributionTest
|
@DistributionTest
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
public class ImportDistTest {
|
public class ImportDistTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testImport(KeycloakDistribution dist) {
|
void testImport(KeycloakDistribution dist) throws IOException {
|
||||||
CLIResult cliResult = dist.run("build");
|
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 of realm 'master' requested.");
|
||||||
cliResult.assertMessage("Export finished successfully");
|
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("Realm 'master' imported");
|
||||||
cliResult.assertMessage("Import finished successfully");
|
cliResult.assertMessage("Import finished successfully");
|
||||||
cliResult.assertNoMessage("Changes detected in configuration");
|
cliResult.assertNoMessage("Changes detected in configuration");
|
||||||
|
|
Loading…
Reference in a new issue