Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made AbstractFilter Denylist settings configurable #925

Merged
Changes from 2 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
43 changes: 30 additions & 13 deletions src/main/java/emissary/output/filter/AbstractFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ public abstract class AbstractFilter implements IDropOffFilter {
@Nullable
protected DropOffUtil dropOffUtil = null;

protected String allowedNameChars = "a-zA-Z0-9_\\-";
protected Pattern allowedNameCharsPattern;
// Match if acceptable characters of denylist items are in correct order
protected String denylistCharSetOrdering = "^[%s*]+(\\.[%s*]+)*$"; // %s = allowed name characters
protected Pattern denylistCharSetOrderingPattern;
// Match if viewname in denylist is formatted correctly
protected String viewNameFormat = "^[%s]+(\\.[%s]+)?\\*?$"; // %s = allowed name characters
protected Pattern viewNameFormatPattern;

/**
* Initialization phase hook for the filter with default preferences for the runtime configuration of the filter
*/
Expand Down Expand Up @@ -118,7 +127,7 @@ public void initialize(final Configurator theConfigG, @Nullable final String fil
initializeOutputTypes(this.filterConfig);
}

private final void loadFilterCondition(final Configurator parentConfig) {
private void loadFilterCondition(final Configurator parentConfig) {
this.filterConditionSpec = parentConfig.findStringEntry("FILTER_CONDITION_" + getFilterName(), null);

// format FILTER_CONDITION_<filtername> = profilename:clazz just like dropoff filter config
Expand Down Expand Up @@ -169,6 +178,7 @@ private final void loadFilterCondition(final Configurator parentConfig) {
*/
protected void initializeOutputTypes(@Nullable final Configurator config) {
if (config != null) {
this.loadNameValidationPatterns(config);
this.outputTypes = config.findEntriesAsSet("OUTPUT_TYPE");
this.logger.debug("Loaded {} output types for filter {}", this.outputTypes.size(), this.outputTypes);
this.initializeDenylist(config);
Expand All @@ -177,18 +187,25 @@ protected void initializeOutputTypes(@Nullable final Configurator config) {
}
}

protected void initializeDenylist(final Configurator config) {
Pattern charSetOrdering = Pattern.compile("^[\\w*]+(\\.[\\w*]+)*$"); // Match if acceptable characters are in correct order
Pattern viewNameFormat = Pattern.compile("^\\w+(\\.\\w+)?\\*?$"); // Match if String is word sequence with optional `*` suffix
protected void loadNameValidationPatterns(final Configurator config) {
allowedNameChars = config.findStringEntry("ALLOWED_NAME_CHARS", allowedNameChars);
allowedNameCharsPattern = Pattern.compile(String.format("[%s]+", allowedNameChars));
denylistCharSetOrdering = config.findStringEntry("DENYLIST_CHARSET_ORDERING", denylistCharSetOrdering);
denylistCharSetOrderingPattern = Pattern.compile(denylistCharSetOrdering.replace("%s", allowedNameChars));
viewNameFormat = config.findStringEntry("VIEWNAME_FORMAT", viewNameFormat);
viewNameFormatPattern = Pattern.compile(viewNameFormat.replace("%s", allowedNameChars));
}

protected void initializeDenylist(final Configurator config) {
for (String entry : config.findEntriesAsSet("DENYLIST")) {
if (charSetOrdering.matcher(entry).matches()) {
if (denylistCharSetOrderingPattern.matcher(entry).matches()) {
String viewName = validateAndRemoveDenylistFiletype(entry);

if (viewName.chars().filter(ch -> ch == '.').count() > 0) {
logger.warn("`DENYLIST = \"{}\"` viewName `{}` should not contain any `.` characters", entry, viewName);
}
if (viewNameFormat.matcher(viewName).matches()) {

if (viewNameFormatPattern.matcher(viewName).matches()) {
if (viewName.endsWith("*")) {
String strippedEntry = entry.substring(0, entry.length() - 1);
this.wildCardDenylist.add(strippedEntry);
Expand All @@ -198,15 +215,15 @@ protected void initializeDenylist(final Configurator config) {
} else {
throw new EmissaryRuntimeException(String.format(
"Invalid filter configuration: `DENYLIST = \"%s\"` " +
"viewName `%s` must be a sequence of [A-Z, a-z, 0-9, _] with optional wildcard `*` suffix.",
entry, viewName));
"viewName `%s` must match pattern `%s`.",
entry, viewName, viewNameFormatPattern.pattern()));
}

} else {
throw new EmissaryRuntimeException(String.format(
"Invalid filter configuration: `DENYLIST = \"%s\"` " +
"must be one sequence of [A-Z, a-z, 0-9, _] or two sequences separated with `.` delimiter.",
entry));
"entry `%s` must match pattern `%s`.",
entry, entry, denylistCharSetOrderingPattern.pattern()));
}
}

Expand All @@ -226,11 +243,11 @@ protected String validateAndRemoveDenylistFiletype(final String entry) {
"Invalid filter configuration: `DENYLIST = \"%s\"` " +
"wildcarded filetypes not allowed in denylist - Did you mean `DENYLIST = \"%s\"`?",
entry, viewName));
} else if (!filetype.chars().allMatch(ch -> Character.isLetterOrDigit(ch) || ch == '_')) { // DENYLIST = "<type>*.<viewName>" not allowed
} else if (!allowedNameCharsPattern.matcher(filetype).matches()) { // DENYLIST = "<type>*.<viewName>" not allowed
throw new EmissaryRuntimeException(String.format(
"Invalid filter configuration: `DENYLIST = \"%s\"` " +
"filetype `%s` must be a sequence of [A-Z, a-z, 0-9, _]",
entry, filetype));
"filetype `%s` must match pattern `%s`",
entry, filetype, allowedNameCharsPattern.pattern()));
}
return viewName;
}
Expand Down