Skip to content

Commit

Permalink
Allow spring boot properties in string substitution.
Browse files Browse the repository at this point in the history
  • Loading branch information
jkroepke committed Feb 10, 2022
1 parent 8a2d2c4 commit 3f48024
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Added

- Allow spring boot properties in string substitution.
- Supports YAML anchors in realm import file

### Fixed
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ keycloak-config-cli is a Keycloak utility to ensure the desired configuration st

# Config files

The config files are based on the keycloak export files. You can use them to re-import your settings.
But keep your files as small as possible. Remove all UUIDs and all stuff which is default set by keycloak.
The config files are based on the keycloak export files. You can use them to re-import your settings. But keep your files as small as possible. Remove all UUIDs and all stuff which is default set by keycloak.

[moped.json](./contrib/example-config/moped.json) is a full working example file you can consider.
Other examples are located in the [test resources](./src/test/resources/import-files).
[moped.json](./contrib/example-config/moped.json) is a full working example file you can consider. Other examples are located in the [test resources](./src/test/resources/import-files).

## Variable Substitution

keycloak-config-cli supports variable substitution of config files. This could be enabled by `import.var-substitution=true` (**disabled by default**).
Use substitutions like

Variables exposed by spring boot (through configtree or [external configuration](https://docs.spring.io/spring-boot/docs/2.5.0/reference/htmlsingle/#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)) can be accessed by `$(property.name)`.

In additional, the string substitution support multiple prefixes for different approaches

```
Base64 Decoder: $(base64Decoder:SGVsbG9Xb3JsZCE=)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.text.StringSubstitutor;
import org.apache.commons.text.lookup.StringLookup;
import org.apache.commons.text.lookup.StringLookupFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
Expand All @@ -56,6 +59,7 @@ public class KeycloakImportProvider {

@Autowired
public KeycloakImportProvider(
Environment environment,
ResourceLoader resourceLoader,
Collection<ResourceExtractor> resourceExtractors,
ImportConfigProperties importConfigProperties
Expand All @@ -68,7 +72,12 @@ public KeycloakImportProvider(
String prefix = importConfigProperties.getVarSubstitutionPrefix();
String suffix = importConfigProperties.getVarSubstitutionSuffix();

StringLookup variableResolver = StringLookupFactory.INSTANCE.interpolatorStringLookup(
StringLookupFactory.INSTANCE.functionStringLookup(environment::getProperty)
);

this.interpolator = StringSubstitutor.createInterpolator()
.setVariableResolver(variableResolver)
.setVariablePrefix(prefix)
.setVariableSuffix(suffix)
.setEnableSubstitutionInVariables(importConfigProperties.isVarSubstitutionInVariables())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetSystemProperty;
import org.keycloak.representations.idm.RealmRepresentation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestPropertySource;

import java.io.IOException;
Expand All @@ -36,13 +38,19 @@
"import.var-substitution=true",
"import.var-substitution-in-variables=false",
"import.var-substitution-undefined-throws-exceptions=false",
"spring.config.import=configtree:src/test/resources/import-files/realm-substitution-extended/configtree/",
"kcc.junit.from.spring-boot.property=value from property"
})

@SetSystemProperty(key = "kcc.junit.display-name", value = "<div class=\\\"kc-logo-text\\\"><span>Keycloak</span></div>")
@SetSystemProperty(key = "kcc.junit.verify-email", value = "true")
@SetSystemProperty(key = "kcc.junit.not-before", value = "1200")
@SetSystemProperty(key = "kcc.junit.browser-security-headers", value = "{\"xRobotsTag\":\"noindex\"}")
class ImportRealmSubstitutionExtendedIT extends AbstractImportTest {

@Autowired
private Environment env;

private static final String REALM_NAME = "realm-substitution-extended";

ImportRealmSubstitutionExtendedIT() {
Expand All @@ -54,12 +62,15 @@ class ImportRealmSubstitutionExtendedIT extends AbstractImportTest {
void shouldCreateRealm() throws IOException {
assertThat(System.getProperty("kcc.junit.display-name"), is("<div class=\\\"kc-logo-text\\\"><span>Keycloak</span></div>"));

assertThat(env.getProperty("kcc.junit.from.spring-boot.property"), is("value from property"));
assertThat(env.getProperty("kcc.junit.from.spring-boot.configtree"), is("value from configtree"));

doImport("0_update_realm.json");

RealmRepresentation realm = keycloakProvider.getInstance().realm(REALM_NAME).toRepresentation();

assertThat(realm.getDisplayName(), is("<div class=\"kc-logo-text\"><span>Keycloak</span></div>"));
assertThat(realm.getDisplayNameHtml(), is(System.getenv("JAVA_HOME")));
assertThat(realm.getDisplayNameHtml(), is(System.getenv("JAVA_HOME") + " - value from property - value from configtree"));
assertThat(realm.isVerifyEmail(), is(Boolean.valueOf(System.getProperty("kcc.junit.verify-email"))));
assertThat(realm.getNotBefore(), is(Integer.valueOf(System.getProperty("kcc.junit.not-before"))));
assertThat(realm.getBrowserSecurityHeaders().get("xRobotsTag"), is("noindex"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"enabled": true,
"realm": "realm-substitution-extended",
"displayName": "$(sys:kcc.junit.display-name)",
"displayNameHtml": "$(env:JAVA_HOME)",
"displayNameHtml": "$(env:JAVA_HOME) - $(kcc.junit.from.spring-boot.property) - $(kcc.junit.from.spring-boot.configtree)",
"verifyEmail": $(sys:kcc.junit.verify-email),
"notBefore": $(sys:kcc.junit.not-before),
"browserSecurityHeaders": $(sys:kcc.junit.browser-security-headers),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
value from configtree

0 comments on commit 3f48024

Please sign in to comment.