Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mkjsix committed Jan 15, 2024
1 parent 8ca4ca0 commit 8b5ab59
Showing 1 changed file with 73 additions and 52 deletions.
125 changes: 73 additions & 52 deletions commons/src/main/java/org/restheart/configuration/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,19 @@
*/
public class Configuration {

private static final String LOG_PATTERN = "\t{} -> {}";

private static final String MASK = "**********";

private static final String LOCALHOST = "localhost";

/**
* the version is read from the JAR's MANIFEST.MF file, which is automatically
* generated by the Maven build process
*/
public static final String VERSION = Configuration.class.getPackage().getImplementationVersion() == null
? "unknown, not packaged"
: Configuration.class.getPackage().getImplementationVersion();
? "unknown, not packaged"
: Configuration.class.getPackage().getImplementationVersion();

static final Logger LOGGER = LoggerFactory.getLogger(Configuration.class);

Expand All @@ -80,9 +86,9 @@ public class Configuration {
*/
private static Path PATH = null;

private static final Listener DEFAULT_HTTP_LISTENER = new Listener(true, "localhost", 8080);
private static final TLSListener DEFAULT_HTTPS_LISTENER = new TLSListener(false, "localhost", 4443, null, null, null);
private static final Listener DEFAULT_AJP_LISTENER = new Listener(false, "localhost", 8009);
private static final Listener DEFAULT_HTTP_LISTENER = new Listener(true, LOCALHOST, 8080);
private static final TLSListener DEFAULT_HTTPS_LISTENER = new TLSListener(false, LOCALHOST, 4443, null, null, null);
private static final Listener DEFAULT_AJP_LISTENER = new Listener(false, LOCALHOST, 8009);

/**
* undertow connetction options
Expand Down Expand Up @@ -111,14 +117,14 @@ public class Configuration {
* @param silent
* @throws org.restheart.configuration.ConfigurationException
*/
private Configuration(Map<String, Object> conf, final Path confFilePath, boolean silent) throws ConfigurationException {
private Configuration(Map<String, Object> conf, final Path confFilePath, boolean silent)
throws ConfigurationException {
PATH = confFilePath;

this.conf = conf;

this.coreModule = CoreModule.build(conf, silent);


if (findOrDefault(conf, Listener.HTTP_LISTENER_KEY, null, true) != null) {
httpListener = new Listener(conf, Listener.HTTP_LISTENER_KEY, DEFAULT_HTTP_LISTENER, silent);
} else {
Expand Down Expand Up @@ -208,7 +214,6 @@ public Listener ajpListener() {
return ajpListener;
}


/**
* @return the logLevel
*/
Expand Down Expand Up @@ -243,6 +248,10 @@ public static Path getPath() {
}

public class Builder {

private Builder() {
}

/**
*
* @param standaloneConfiguration
Expand All @@ -261,9 +270,11 @@ public static Configuration build(boolean standaloneConfiguration, boolean silen
* @param silent
* @return return the configuration from confFile and propFile
*/
public static Configuration build(Path confFilePath, Path confOverridesFilePath, boolean standaloneConfiguration, boolean silent) throws ConfigurationException {
public static Configuration build(Path confFilePath, Path confOverridesFilePath,
boolean standaloneConfiguration, boolean silent) throws ConfigurationException {
if (confFilePath == null) {
var defaultConfFilePath = standaloneConfiguration ? "/restheart-default-config-no-mongodb.yml" : "/restheart-default-config.yml";
var defaultConfFilePath = standaloneConfiguration ? "/restheart-default-config-no-mongodb.yml"
: "/restheart-default-config.yml";
var stream = Configuration.class.getResourceAsStream(defaultConfFilePath);
try (var confReader = new InputStreamReader(stream)) {
return build(confReader, null, confOverridesFilePath, silent);
Expand All @@ -286,36 +297,41 @@ public static Configuration build(Path confFilePath, Path confOverridesFilePath,
* @param confFile
* @return return the configuration from confFile and propFile
*/
private static Configuration build(Reader confReader, Path confFilePath, Path confOverridesFilePath, boolean silent) throws ConfigurationException {
private static Configuration build(Reader confReader, Path confFilePath, Path confOverridesFilePath,
boolean silent) throws ConfigurationException {
Map<String, Object> confMap = new Yaml(new SafeConstructor(new LoaderOptions())).load(confReader);

if (confOverridesFilePath != null) {
try {
String overrides;

if (confOverridesFilePath.toString().toLowerCase().endsWith(".yml")
|| confOverridesFilePath.toString().toLowerCase().endsWith(".yaml")) {
|| confOverridesFilePath.toString().toLowerCase().endsWith(".yaml")) {
// YML format
try {
overrides = fromYmlToRho(Files.newBufferedReader(confOverridesFilePath));
} catch(JsonParseException jpe) {
throw new ConfigurationException("Wrong configuration override YML file: " + jpe.getLocalizedMessage(), jpe, false);
} catch (JsonParseException jpe) {
throw new ConfigurationException(
"Wrong configuration override YML file: " + jpe.getLocalizedMessage(), jpe, false);
}
} else if (confOverridesFilePath.toString().toLowerCase().endsWith(".json")
|| confOverridesFilePath.toString().toLowerCase().endsWith(".jsonc")) {
|| confOverridesFilePath.toString().toLowerCase().endsWith(".jsonc")) {
// JSON format
try {
overrides = fromJsonToRho(Files.newBufferedReader(confOverridesFilePath));
} catch(JsonParseException jpe) {
throw new ConfigurationException("Wrong configuration override JSON file: " + jpe.getLocalizedMessage(), jpe, false);
} catch (JsonParseException jpe) {
throw new ConfigurationException(
"Wrong configuration override JSON file: " + jpe.getLocalizedMessage(), jpe, false);
}
} else if (confOverridesFilePath.toString().toLowerCase().endsWith(".conf")) {
// RHO format
overrides = Files.readAllLines(confOverridesFilePath).stream()
.filter(row -> !row.strip().startsWith("#")) // ingore comments lines
.collect(Collectors.joining());
.filter(row -> !row.strip().startsWith("#")) // ingore comments lines
.collect(Collectors.joining());
} else {
throw new ConfigurationException("Configuration override file must have .json, .jsonc, .yml, .yaml or .conf extension: " + confOverridesFilePath);
throw new ConfigurationException(
"Configuration override file must have .json, .jsonc, .yml, .yaml or .conf extension: "
+ confOverridesFilePath);
}

if (!silent) {
Expand All @@ -324,7 +340,8 @@ private static Configuration build(Reader confReader, Path confFilePath, Path co

confMap = overrideConfiguration(confMap, overrides(overrides, true, silent), silent);
} catch (IOException ioe) {
throw new ConfigurationException("Configuration override file not found: " + confOverridesFilePath, ioe, false);
throw new ConfigurationException("Configuration override file not found: " + confOverridesFilePath,
ioe, false);
}
}

Expand Down Expand Up @@ -355,8 +372,8 @@ private static String fromJsonToRho(Reader jsonReader) throws JsonParseException
var obj = _json.getAsJsonObject();

return obj.entrySet().stream()
.map(e -> e.getKey() + "->" + e.getValue().toString())
.collect(Collectors.joining(";"));
.map(e -> e.getKey() + "->" + e.getValue().toString())
.collect(Collectors.joining(";"));
}

// converst a YMM configuration override file into the RHO syntax
Expand All @@ -372,63 +389,67 @@ private static String fromYmlToRho(Reader yml) throws JsonParseException {
final var gson = new GsonBuilder().serializeNulls().create();

return _yml.entrySet().stream()
.map(e -> e.getKey() + "->" + gson.toJson(e.getValue()))
.collect(Collectors.joining(";"));
.map(e -> e.getKey() + "->" + gson.toJson(e.getValue()))
.collect(Collectors.joining(";"));
}

/**
*
* @param confMap
* @return
*/
private static Map<String, Object> overrideConfiguration(Map<String, Object> confMap, List<RhOverride> overrides, final boolean silent) {
private static Map<String, Object> overrideConfiguration(Map<String, Object> confMap, List<RhOverride> overrides,
final boolean silent) {
var ctx = JXPathContext.newContext(confMap);
ctx.setLenient(true);

// this logs the overrides trying to mask sensite data
// sensitive data is any key containins "password", "pwd" or "secret"
// it also hides the password in MongoDB connection string
// works also if the value is a Json object, checking the root keys (does not hide nested properties)
// works also if the value is a Json object, checking the root keys (does not
// hide nested properties)
overrides.stream().forEachOrdered(o -> {
if (!silent) {
if (o.value() instanceof HashMap<?, ?> mapValue) {
var maskedValue = new HashMap<>();
mapValue.keySet().stream()
.filter(k -> k instanceof String)
.map(k -> (String) k)
.forEach(k -> {
if (k.contains("password") || k.contains("pwd") || k.contains("secret") || k.contains("key")) {
maskedValue.put(k, "**********");
} else if (k.contains("connection-string")) {
try {
var svalue = mapValue.get(k).toString();
var cs = new ConnectionString(svalue);
var _pwd = cs.getPassword();
if (_pwd != null) {
var pwd = new String(_pwd);
maskedValue.put(k, svalue.replaceFirst(pwd, "**********"));
.filter(k -> k instanceof String)
.map(k -> (String) k)
.forEach(k -> {
if (k.contains("password") || k.contains("pwd") || k.contains("secret")
|| k.contains("key")) {
maskedValue.put(k, MASK);
} else if (k.contains("connection-string")) {
try {
var svalue = mapValue.get(k).toString();
var cs = new ConnectionString(svalue);
var _pwd = cs.getPassword();
if (_pwd != null) {
var pwd = new String(_pwd);
maskedValue.put(k, svalue.replaceFirst(pwd, MASK));
}
} catch (Throwable t) {
maskedValue.put(k, mapValue);
}
} catch(Throwable t) {
maskedValue.put(k, mapValue);
}
}
});
LOGGER.info("\t{} -> {}", o.path(), maskedValue);
} else if (o.path().contains("password") || o.path().contains("pwd") || o.path().contains("secret") || o.path().contains("key")) {
LOGGER.info("\t{} -> {}", o.path(), "**********");
});
LOGGER.info(LOG_PATTERN, o.path(), maskedValue);
} else if (o.path().contains("password") || o.path().contains("pwd") || o.path().contains("secret")
|| o.path().contains("key")) {
LOGGER.info(LOG_PATTERN, o.path(), MASK);
} else if (o.path().endsWith("connection-string") && o.value() instanceof String svalue) {
try {
var cs = new ConnectionString(svalue);
var _pwd = cs.getPassword();
if (_pwd != null) {
var pwd = new String(_pwd);
LOGGER.info("\t{} -> {}", o.path(), svalue.replaceFirst(pwd, "**********"));
LOGGER.info(LOG_PATTERN, o.path(), svalue.replaceFirst(pwd, MASK));
}
} catch(Throwable t) {
LOGGER.info("\t{} -> {}", o.path(), o.value());
} catch (Throwable t) {
LOGGER.info(LOG_PATTERN, o.path(), o.value());
}
} else {
LOGGER.info("\t{} -> {}", o.path(), o.value());
LOGGER.info(LOG_PATTERN, o.path(), o.value());
}
}

Expand All @@ -437,7 +458,7 @@ private static Map<String, Object> overrideConfiguration(Map<String, Object> con
} else {
try {
createPathAndSetValue(ctx, o.path(), o.value());
} catch(Throwable ise) {
} catch (Throwable ise) {
LOGGER.error("Wrong configuration override {}, {}", o.raw(), ise.getMessage());
}
}
Expand Down

0 comments on commit 8b5ab59

Please sign in to comment.