mirror of
https://github.com/lightbend/config.git
synced 2025-01-13 13:50:35 +08:00
fix: Optionally hide rendered environment variables (#798)
* new OriginType.ENV_VARIABLE * deserialization of unknown originType ordinal, but this doesn't really help for compatibility if serialized with new version and deserialized with old version
This commit is contained in:
parent
5d6a46631c
commit
3a4ebbfd02
@ -95,7 +95,11 @@ lazy val configLib = Project("config", file("config"))
|
||||
"CONFIG_FORCE_a__c" -> "3",
|
||||
"CONFIG_FORCE_a___c" -> "4",
|
||||
"CONFIG_FORCE_akka_version" -> "foo",
|
||||
"CONFIG_FORCE_akka_event__handler__dispatcher_max__pool__size" -> "10")
|
||||
"CONFIG_FORCE_akka_event__handler__dispatcher_max__pool__size" -> "10",
|
||||
"SECRET_A" -> "A", // ConfigTest.renderShowEnvVariableValues
|
||||
"SECRET_B" -> "B", // ConfigTest.renderShowEnvVariableValues
|
||||
"SECRET_C" -> "C" // ConfigTest.renderShowEnvVariableValues
|
||||
)
|
||||
|
||||
OsgiKeys.exportPackage := Seq("com.typesafe.config", "com.typesafe.config.impl")
|
||||
publish := sys.error("use publishSigned instead of plain publish")
|
||||
|
@ -21,13 +21,15 @@ public final class ConfigRenderOptions {
|
||||
private final boolean comments;
|
||||
private final boolean formatted;
|
||||
private final boolean json;
|
||||
private final boolean showEnvVariableValues;
|
||||
|
||||
private ConfigRenderOptions(boolean originComments, boolean comments, boolean formatted,
|
||||
boolean json) {
|
||||
boolean json, boolean showEnvVariableValues) {
|
||||
this.originComments = originComments;
|
||||
this.comments = comments;
|
||||
this.formatted = formatted;
|
||||
this.json = json;
|
||||
this.showEnvVariableValues = showEnvVariableValues;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,7 +40,7 @@ public final class ConfigRenderOptions {
|
||||
* @return the default render options
|
||||
*/
|
||||
public static ConfigRenderOptions defaults() {
|
||||
return new ConfigRenderOptions(true, true, true, true);
|
||||
return new ConfigRenderOptions(true, true, true, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +50,7 @@ public final class ConfigRenderOptions {
|
||||
* @return the concise render options
|
||||
*/
|
||||
public static ConfigRenderOptions concise() {
|
||||
return new ConfigRenderOptions(false, false, false, true);
|
||||
return new ConfigRenderOptions(false, false, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +66,7 @@ public final class ConfigRenderOptions {
|
||||
if (value == comments)
|
||||
return this;
|
||||
else
|
||||
return new ConfigRenderOptions(originComments, value, formatted, json);
|
||||
return new ConfigRenderOptions(originComments, value, formatted, json, showEnvVariableValues);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +99,7 @@ public final class ConfigRenderOptions {
|
||||
if (value == originComments)
|
||||
return this;
|
||||
else
|
||||
return new ConfigRenderOptions(value, comments, formatted, json);
|
||||
return new ConfigRenderOptions(value, comments, formatted, json, showEnvVariableValues);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,7 +124,7 @@ public final class ConfigRenderOptions {
|
||||
if (value == formatted)
|
||||
return this;
|
||||
else
|
||||
return new ConfigRenderOptions(originComments, comments, value, json);
|
||||
return new ConfigRenderOptions(originComments, comments, value, json, showEnvVariableValues);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +152,32 @@ public final class ConfigRenderOptions {
|
||||
if (value == json)
|
||||
return this;
|
||||
else
|
||||
return new ConfigRenderOptions(originComments, comments, formatted, value);
|
||||
return new ConfigRenderOptions(originComments, comments, formatted, value, showEnvVariableValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns options with showEnvVariableValues toggled. This controls if values set from
|
||||
* environment variables are included in the rendered string.
|
||||
*
|
||||
* @param value
|
||||
* true to include environment variable values in the render
|
||||
* @return options with requested setting for environment variables
|
||||
*/
|
||||
public ConfigRenderOptions setShowEnvVariableValues(boolean value) {
|
||||
if (value == showEnvVariableValues)
|
||||
return this;
|
||||
else
|
||||
return new ConfigRenderOptions(originComments, comments, formatted, json, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the options enable rendering of environment variable values. This method is mostly used
|
||||
* by the config lib internally, not by applications.
|
||||
*
|
||||
* @return true if environment variable values should be rendered
|
||||
*/
|
||||
public boolean getShowEnvVariableValues() {
|
||||
return showEnvVariableValues;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,6 +201,8 @@ public final class ConfigRenderOptions {
|
||||
sb.append("formatted,");
|
||||
if (json)
|
||||
sb.append("json,");
|
||||
if (showEnvVariableValues)
|
||||
sb.append("showEnvVariableValues,");
|
||||
if (sb.charAt(sb.length() - 1) == ',')
|
||||
sb.setLength(sb.length() - 1);
|
||||
sb.append(")");
|
||||
|
@ -357,8 +357,20 @@ abstract class AbstractConfigValue implements ConfigValue, MergeableValue {
|
||||
}
|
||||
|
||||
protected void render(StringBuilder sb, int indent, boolean atRoot, ConfigRenderOptions options) {
|
||||
Object u = unwrapped();
|
||||
sb.append(u.toString());
|
||||
if (hideEnvVariableValue(options)) {
|
||||
sb.append("<env variable>");
|
||||
} else {
|
||||
Object u = unwrapped();
|
||||
sb.append(u.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hideEnvVariableValue(ConfigRenderOptions options) {
|
||||
return !options.getShowEnvVariableValues() && origin.originType() == OriginType.ENV_VARIABLE;
|
||||
}
|
||||
|
||||
protected void appendHiddenEnvVariableValue(StringBuilder sb) {
|
||||
sb.append("\"<env variable>\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -342,7 +342,7 @@ public class ConfigImpl {
|
||||
}
|
||||
|
||||
private static AbstractConfigObject loadEnvVariables() {
|
||||
return PropertiesParser.fromStringMap(newSimpleOrigin("env variables"), System.getenv());
|
||||
return PropertiesParser.fromStringMap(newEnvVariable("env variables"), System.getenv());
|
||||
}
|
||||
|
||||
private static class EnvVariablesHolder {
|
||||
@ -544,4 +544,8 @@ public class ConfigImpl {
|
||||
public static ConfigOrigin newURLOrigin(URL url) {
|
||||
return SimpleConfigOrigin.newURL(url);
|
||||
}
|
||||
|
||||
public static ConfigOrigin newEnvVariable(String description) {
|
||||
return SimpleConfigOrigin.newEnvVariable(description);
|
||||
}
|
||||
}
|
||||
|
@ -80,11 +80,15 @@ abstract class ConfigString extends AbstractConfigValue implements Serializable
|
||||
|
||||
@Override
|
||||
protected void render(StringBuilder sb, int indent, boolean atRoot, ConfigRenderOptions options) {
|
||||
String rendered;
|
||||
if (options.getJson())
|
||||
rendered = ConfigImplUtil.renderJsonString(value);
|
||||
else
|
||||
rendered = ConfigImplUtil.renderStringUnquotedIfPossible(value);
|
||||
sb.append(rendered);
|
||||
if (hideEnvVariableValue(options)) {
|
||||
appendHiddenEnvVariableValue(sb);
|
||||
} else {
|
||||
String rendered;
|
||||
if (options.getJson())
|
||||
rendered = ConfigImplUtil.renderJsonString(value);
|
||||
else
|
||||
rendered = ConfigImplUtil.renderStringUnquotedIfPossible(value);
|
||||
sb.append(rendered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,5 +5,6 @@ enum OriginType {
|
||||
GENERIC,
|
||||
FILE,
|
||||
URL,
|
||||
RESOURCE
|
||||
RESOURCE,
|
||||
ENV_VARIABLE
|
||||
}
|
||||
|
@ -77,6 +77,10 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
||||
return newResource(resource, null);
|
||||
}
|
||||
|
||||
static SimpleConfigOrigin newEnvVariable(String description) {
|
||||
return new SimpleConfigOrigin(description, -1, -1, OriginType.ENV_VARIABLE, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleConfigOrigin withLineNumber(int lineNumber) {
|
||||
if (lineNumber == this.lineNumber && lineNumber == this.endLineNumber) {
|
||||
@ -139,6 +143,10 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
||||
}
|
||||
}
|
||||
|
||||
OriginType originType() {
|
||||
return originType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof SimpleConfigOrigin) {
|
||||
@ -484,7 +492,11 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
||||
Number originTypeOrdinal = (Number) m.get(SerializedField.ORIGIN_TYPE);
|
||||
if (originTypeOrdinal == null)
|
||||
throw new IOException("Missing ORIGIN_TYPE field");
|
||||
OriginType originType = OriginType.values()[originTypeOrdinal.byteValue()];
|
||||
OriginType originType;
|
||||
if (originTypeOrdinal.byteValue() < OriginType.values().length)
|
||||
originType = OriginType.values()[originTypeOrdinal.byteValue()];
|
||||
else
|
||||
originType = OriginType.GENERIC; // ENV_VARIABLE was added in a later version
|
||||
String urlOrNull = (String) m.get(SerializedField.ORIGIN_URL);
|
||||
String resourceOrNull = (String) m.get(SerializedField.ORIGIN_RESOURCE);
|
||||
@SuppressWarnings("unchecked")
|
||||
|
4
config/src/test/resources/env-variables.conf
Normal file
4
config/src/test/resources/env-variables.conf
Normal file
@ -0,0 +1,4 @@
|
||||
secret = a
|
||||
secret = ${?SECRET_A}
|
||||
secrets = ["b", "c"]
|
||||
secrets = [${?SECRET_B}, ${?SECRET_C}]
|
@ -1,3 +1,5 @@
|
||||
package foo;
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
|
||||
@ -6,11 +8,13 @@ object RenderExample extends App {
|
||||
val originComments = args.contains("--origin-comments")
|
||||
val comments = args.contains("--comments")
|
||||
val hocon = args.contains("--hocon")
|
||||
val hideEnvVariableValues = args.contains("--hide-env-variable-values")
|
||||
val options = ConfigRenderOptions.defaults()
|
||||
.setFormatted(formatted)
|
||||
.setOriginComments(originComments)
|
||||
.setComments(comments)
|
||||
.setJson(!hocon)
|
||||
.setShowEnvVariableValues(!hideEnvVariableValues)
|
||||
|
||||
def render(what: String) {
|
||||
val conf = ConfigFactory.defaultOverrides()
|
||||
|
@ -1207,6 +1207,35 @@ class ConfigTest extends TestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def renderShowEnvVariableValues(): Unit = {
|
||||
val config = ConfigFactory.load("env-variables")
|
||||
assertEquals("A", config.getString("secret"))
|
||||
assertEquals("B", config.getStringList("secrets").get(0))
|
||||
assertEquals("C", config.getStringList("secrets").get(1))
|
||||
val hideRenderOpt = ConfigRenderOptions.defaults().setShowEnvVariableValues(false)
|
||||
val rendered1 = config.root().render(hideRenderOpt)
|
||||
assertTrue(rendered1.contains(""""secret" : "<env variable>""""))
|
||||
assertTrue(rendered1.contains(
|
||||
"""| "secrets" : [
|
||||
| # env variables
|
||||
| "<env variable>",
|
||||
| # env variables
|
||||
| "<env variable>"
|
||||
| ]""".stripMargin))
|
||||
|
||||
val showRenderOpt = ConfigRenderOptions.defaults()
|
||||
val rendered2 = config.root().render(showRenderOpt)
|
||||
assertTrue(rendered2.contains(""""secret" : "A""""))
|
||||
assertTrue(rendered2.contains(
|
||||
"""| "secrets" : [
|
||||
| # env variables
|
||||
| "B",
|
||||
| # env variables
|
||||
| "C"
|
||||
| ]""".stripMargin))
|
||||
}
|
||||
|
||||
@Test
|
||||
def serializeRoundTrip() {
|
||||
for (i <- 1 to 10) {
|
||||
|
Loading…
Reference in New Issue
Block a user