Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dotCMS/src/main/java/com/dotcms/business/SystemTableImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.dotcms.api.system.event.Payload;
import com.dotcms.api.system.event.SystemEventType;
import com.dotcms.rest.api.v1.maintenance.JVMInfoResource;
import com.dotcms.util.ObfuscationUtil;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.FactoryLocator;
import com.dotmarketing.db.HibernateUtil;
Expand Down Expand Up @@ -69,7 +69,7 @@ public Map<String, String> all() {
@WrapInTransaction
public void set(final String key, final String value) {

SecurityLogger.logInfo(this.getClass(), "Saving system table value for key:" + key + "=" + JVMInfoResource.obfuscateIfNeeded(
SecurityLogger.logInfo(this.getClass(), "Saving system table value for key:" + key + "=" + ObfuscationUtil.obfuscateIfNeeded(
key,value));

Try.run(()-> this.systemTableFactory.saveOrUpdate(key, value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.dotcms.business.SystemTable;
import com.dotcms.rest.InitDataObject;
import com.dotcms.util.ObfuscationUtil;
import com.dotcms.rest.WebResource;
import com.dotcms.rest.annotation.NoCache;
import com.dotmarketing.business.APILocator;
Expand Down Expand Up @@ -37,14 +38,13 @@
@SuppressWarnings("serial")
public class JVMInfoResource implements Serializable {

private static final String DEFAULT_OBFUSCATE_PATTERN = "passw|pass|passwd|secret|key|token";
/** @deprecated use {@link ObfuscationUtil#BASE_PATTERN} */
@Deprecated
public static final Pattern obfuscateBasePattern = ObfuscationUtil.BASE_PATTERN;

public static final Pattern obfuscateBasePattern = Pattern.compile(DEFAULT_OBFUSCATE_PATTERN,
Pattern.CASE_INSENSITIVE);

public static final Pattern obfuscatePattern = Pattern.compile(
Config.getStringProperty("OBFUSCATE_SYSTEM_ENVIRONMENTAL_VARIABLES", DEFAULT_OBFUSCATE_PATTERN),
Pattern.CASE_INSENSITIVE);
/** @deprecated use {@link ObfuscationUtil#CUSTOM_PATTERN} */
@Deprecated
public static final Pattern obfuscatePattern = ObfuscationUtil.CUSTOM_PATTERN;

@Path("/")
@GET
Expand Down Expand Up @@ -116,10 +116,8 @@ private Map<String, Object> getDBOverrides(){

SystemTable systemTable =APILocator.getSystemAPI().getSystemTable();

resultMap.putAll(systemTable.all());



systemTable.all().forEach((key, value) ->
resultMap.put(key, ObfuscationUtil.obfuscateIfNeeded(key, value)));

return resultMap;
}
Expand Down Expand Up @@ -155,7 +153,7 @@ private Map<String,Object> getSystemProps(){
Properties props = System.getProperties();
for(Object keyObject : props.keySet()) {
final String key = (String) keyObject;
resultMap.put(key, obfuscateIfNeeded(key,props.getProperty(key)));
resultMap.put(key, ObfuscationUtil.obfuscateIfNeeded(key, props.getProperty(key)));
}

return resultMap;
Expand All @@ -168,7 +166,7 @@ private Map<String,Object> getEnvironmentalVars(){
final Map<String,Object> resultMap=new LinkedHashMap<>();
Map<String,String> vars = System.getenv();
for(String key : vars.keySet()) {
resultMap.put(key, obfuscateIfNeeded(key,vars.get(key)));
resultMap.put(key, ObfuscationUtil.obfuscateIfNeeded(key, vars.get(key)));
}

return resultMap;
Expand All @@ -191,18 +189,10 @@ private Map<String,Object> getReleaseInfo(){



/** @deprecated use {@link ObfuscationUtil#obfuscateIfNeeded(String, Object)} */
@Deprecated
public static String obfuscateIfNeeded(final String key, final Object valueObject) {
final String value = (String) valueObject;
if(UtilMethods.isEmpty(value)) return "";
return obfuscateBasePattern.matcher(key).find() || obfuscatePattern.matcher(key).find()
? obfuscate(value)
: value;
}

private static String obfuscate(final String value) {
return value.charAt(0)
+ "*********"
+ value.charAt(value.length() - 1);
return ObfuscationUtil.obfuscateIfNeeded(key, valueObject);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.dotcms.featureflag.FeatureFlagName;
import com.dotcms.rest.InitDataObject;
import com.dotcms.rest.WebResource.InitBuilder;
import com.dotcms.rest.api.v1.maintenance.JVMInfoResource;
import com.dotcms.util.ObfuscationUtil;
import com.dotcms.rest.api.v1.pagescanner.PageScannerResource;
import com.dotmarketing.util.StringUtils;
import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -115,7 +115,7 @@ public class ConfigurationResource implements Serializable {
FeatureFlagName.IMAGE_API_USE_LIBVIPS }));

private boolean isOnBlackList(final String key) {
return null != JVMInfoResource.obfuscatePattern ? JVMInfoResource.obfuscatePattern.matcher(key).find() : false;
return ObfuscationUtil.matchesCustomPattern(key);
}

/**
Expand Down
74 changes: 74 additions & 0 deletions dotCMS/src/main/java/com/dotcms/util/ObfuscationUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.dotcms.util;

import com.dotmarketing.util.Config;
import com.dotmarketing.util.UtilMethods;
import java.util.regex.Pattern;

/**
* Central place for the key-name based obfuscation rules used when rendering potentially
* sensitive configuration to users — the JVM info screen ({@code /api/v1/jvm}), the
* configuration REST endpoint, security logging, etc.
* <p>
* A value is masked when its key matches either the built-in {@link #DEFAULT_OBFUSCATE_PATTERN}
* or the deployment-specific pattern configured via the
* {@code OBFUSCATE_SYSTEM_ENVIRONMENTAL_VARIABLES} property.
*/
public final class ObfuscationUtil {

public static final String DEFAULT_OBFUSCATE_PATTERN = "passw|pass|passwd|secret|key|token";

/**
* The always-on rules — not overridable, so a misconfigured custom pattern can never
* un-mask the obvious cases.
*/
public static final Pattern BASE_PATTERN =
Pattern.compile(DEFAULT_OBFUSCATE_PATTERN, Pattern.CASE_INSENSITIVE);

/**
* Deployment-specific rules from {@code OBFUSCATE_SYSTEM_ENVIRONMENTAL_VARIABLES};
* defaults to the same expression as {@link #BASE_PATTERN}.
*/
public static final Pattern CUSTOM_PATTERN = Pattern.compile(
Config.getStringProperty("OBFUSCATE_SYSTEM_ENVIRONMENTAL_VARIABLES",
DEFAULT_OBFUSCATE_PATTERN),
Pattern.CASE_INSENSITIVE);

private ObfuscationUtil() {
}

/**
* @return true when the key matches the built-in or the configured custom pattern
*/
public static boolean shouldObfuscate(final String key) {
return BASE_PATTERN.matcher(key).find() || CUSTOM_PATTERN.matcher(key).find();
}

/**
* @return true when the key matches only the configured custom pattern (used by callers
* that intentionally honor just the {@code OBFUSCATE_SYSTEM_ENVIRONMENTAL_VARIABLES} rules)
*/
public static boolean matchesCustomPattern(final String key) {
return CUSTOM_PATTERN.matcher(key).find();
}

/**
* Masks the value when the key matches the obfuscation rules; returns it untouched otherwise.
*/
public static String obfuscateIfNeeded(final String key, final Object valueObject) {
final String value = (String) valueObject;
if (UtilMethods.isEmpty(value)) {
return "";
}
return shouldObfuscate(key) ? obfuscate(value) : value;
}

/**
* Masks a value keeping only its first and last character, e.g. {@code s*********t}.
*/
public static String obfuscate(final String value) {
return value.charAt(0)
+ "*********"
+ value.charAt(value.length() - 1);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ public class ConfigurationResourceTest {
void setUp() {
// Open the Config mock BEFORE constructing ConfigurationResource so that
// any static initializer that calls Config (WHITE_LIST, and
// JVMInfoResource.obfuscatePattern via isOnBlackList) receives a safe
// ObfuscationUtil.CUSTOM_PATTERN via isOnBlackList) receives a safe
// default instead of null. Without this, Pattern.compile(null) inside
// JVMInfoResource throws NullPointerException on first class load.
// ObfuscationUtil throws NullPointerException on first class load.
//
// Default answer: return the caller-supplied default (second argument)
// for any getStringProperty / getStringArrayProperty call that is not
Expand Down
Loading