Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import okio.Okio;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -99,7 +99,11 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {

private boolean hasUserWafConfig;
private boolean defaultConfigActivated;
private final Set<String> usedDDWafConfigKeys = new HashSet<>();
private final AtomicBoolean subscribedToRulesAndData = new AtomicBoolean();
private final Set<String> usedDDWafConfigKeys =
Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set<String> ignoredConfigKeys =
Collections.newSetFromMap(new ConcurrentHashMap<>());
private final String DEFAULT_WAF_CONFIG_RULE = "DEFAULT_WAF_CONFIG";
private String currentRuleVersion;
private List<AppSecModule> modulesToUpdateVersionIn;
Expand All @@ -122,13 +126,15 @@ private void subscribeConfigurationPoller() {
subscribeAsmFeatures();

if (!hasUserWafConfig) {
subscribeRulesAndData();
updateRulesAndDataSubscription();
} else {
log.debug("Will not subscribe to ASM, ASM_DD and ASM_DATA (AppSec custom rules in use)");
}

this.configurationPoller.addConfigurationEndListener(applyRemoteConfigListener);
}

private long getRulesAndDataCapabilities() {
long capabilities =
CAPABILITY_ASM_DD_RULES
| CAPABILITY_ASM_IP_BLOCKING
Expand All @@ -154,13 +160,36 @@ private void subscribeConfigurationPoller() {
capabilities |= CAPABILITY_ASM_RASP_LFI;
}
}
this.configurationPoller.addCapabilities(capabilities);
return capabilities;
}

private void updateRulesAndDataSubscription() {
if (hasUserWafConfig) {
return; // do nothing if the customer has custom rules
}
if (AppSecSystem.isActive()) {
subscribeRulesAndData();
} else {
unsubscribeRulesAndData();
}
}

private void subscribeRulesAndData() {
this.configurationPoller.addListener(Product.ASM_DD, new AppSecConfigChangesDDListener());
this.configurationPoller.addListener(Product.ASM_DATA, new AppSecConfigChangesListener());
this.configurationPoller.addListener(Product.ASM, new AppSecConfigChangesListener());
if (subscribedToRulesAndData.compareAndSet(false, true)) {
this.configurationPoller.addListener(Product.ASM_DD, new AppSecConfigChangesDDListener());
this.configurationPoller.addListener(Product.ASM_DATA, new AppSecConfigChangesListener());
this.configurationPoller.addListener(Product.ASM, new AppSecConfigChangesListener());
this.configurationPoller.addCapabilities(getRulesAndDataCapabilities());
}
}

private void unsubscribeRulesAndData() {
if (subscribedToRulesAndData.compareAndSet(true, false)) {
this.configurationPoller.removeListeners(Product.ASM_DD);
this.configurationPoller.removeListeners(Product.ASM_DATA);
this.configurationPoller.removeListeners(Product.ASM);
this.configurationPoller.removeCapabilities(getRulesAndDataCapabilities());
}
}

public void modulesToUpdateVersionIn(List<AppSecModule> modules) {
Expand All @@ -175,19 +204,21 @@ private class AppSecConfigChangesListener implements ProductListener {
@Override
public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollingRateHinter)
throws IOException {
maybeInitializeDefaultConfig();

if (content == null) {
try {
wafBuilder.removeConfig(configKey.toString());
} catch (UnclassifiedWafException e) {
throw new RuntimeException(e);
}
remove(configKey, pollingRateHinter);
return;
}
final String key = configKey.toString();
Map<String, Object> contentMap =
ADAPTER.fromJson(Okio.buffer(Okio.source(new ByteArrayInputStream(content))));
if (contentMap == null || contentMap.isEmpty()) {
ignoredConfigKeys.add(key);
} else {
Map<String, Object> contentMap =
ADAPTER.fromJson(Okio.buffer(Okio.source(new ByteArrayInputStream(content))));
ignoredConfigKeys.remove(key);
try {
handleWafUpdateResultReport(configKey.toString(), contentMap);
beforeApply(key, contentMap);
maybeInitializeDefaultConfig();
handleWafUpdateResultReport(key, contentMap);
} catch (AppSecModule.AppSecModuleActivationException e) {
throw new RuntimeException(e);
}
Expand All @@ -197,19 +228,32 @@ public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollin
@Override
public void remove(ConfigKey configKey, PollingRateHinter pollingRateHinter)
throws IOException {
accept(configKey, null, pollingRateHinter);
final String key = configKey.toString();
if (ignoredConfigKeys.remove(key)) {
return;
}
try {
maybeInitializeDefaultConfig();
wafBuilder.removeConfig(key);
afterRemove(key);
} catch (UnclassifiedWafException e) {
throw new RuntimeException(e);
}
}

@Override
public void commit(PollingRateHinter pollingRateHinter) {
// no action needed
}

protected void beforeApply(final String key, final Map<String, Object> contentMap) {}

protected void afterRemove(final String key) {}
}

private class AppSecConfigChangesDDListener extends AppSecConfigChangesListener {
@Override
public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollingRateHinter)
throws IOException {
protected void beforeApply(final String key, final Map<String, Object> config) {
if (defaultConfigActivated) { // if we get any config, remove the default one
log.debug("Removing default config");
try {
Expand All @@ -219,15 +263,12 @@ public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollin
}
defaultConfigActivated = false;
}
usedDDWafConfigKeys.add(configKey.toString());
super.accept(configKey, content, pollingRateHinter);
usedDDWafConfigKeys.add(key);
}

@Override
public void remove(ConfigKey configKey, PollingRateHinter pollingRateHinter)
throws IOException {
super.remove(configKey, pollingRateHinter);
usedDDWafConfigKeys.remove(configKey.toString());
protected void afterRemove(final String key) {
usedDDWafConfigKeys.remove(key);
}
}

Expand Down Expand Up @@ -282,7 +323,6 @@ private void subscribeAsmFeatures() {
Product.ASM_FEATURES,
AppSecFeaturesDeserializer.INSTANCE,
(configKey, newConfig, hinter) -> {
maybeInitializeDefaultConfig();
if (newConfig == null) {
mergedAsmFeatures.removeConfig(configKey);
} else {
Expand Down Expand Up @@ -339,8 +379,6 @@ public void init() {
} else {
hasUserWafConfig = true;
}
this.mergedAsmFeatures.clear();
this.usedDDWafConfigKeys.clear();

if (wafConfig.isEmpty()) {
throw new IllegalStateException("Expected default waf config to be available");
Expand All @@ -353,9 +391,12 @@ public void init() {
}

public void maybeSubscribeConfigPolling() {
final ProductActivation appSecActivation = tracerConfig.getAppSecActivation();
if (appSecActivation == ProductActivation.FULLY_DISABLED) {
return; // shouldn't happen but just in case.
}
if (this.configurationPoller != null) {
if (hasUserWafConfig
&& tracerConfig.getAppSecActivation() == ProductActivation.FULLY_ENABLED) {
if (hasUserWafConfig && appSecActivation == ProductActivation.FULLY_ENABLED) {
log.info(
"AppSec will not use remote config because "
+ "there is a custom user configuration and AppSec is explicitly enabled");
Expand Down Expand Up @@ -494,6 +535,7 @@ public void close() {
this.configurationPoller.removeListeners(Product.ASM);
this.configurationPoller.removeListeners(Product.ASM_FEATURES);
this.configurationPoller.removeConfigurationEndListener(applyRemoteConfigListener);
this.subscribedToRulesAndData.set(false);
this.configurationPoller.stop();
if (this.wafBuilder != null) {
this.wafBuilder.close();
Expand Down Expand Up @@ -526,6 +568,7 @@ private void setAppSecActivation(final AppSecFeatures.Asm asm) {
if (AppSecSystem.isActive() != newState) {
log.info("AppSec {} (runtime)", newState ? "enabled" : "disabled");
AppSecSystem.setActive(newState);
updateRulesAndDataSubscription();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private static boolean initWAF() {
try {
boolean simpleLoad = System.getProperty("POWERWAF_SIMPLE_LOAD") != null;
Waf.initialize(simpleLoad);
} catch (Exception e) {
} catch (Throwable e) {
Logger logger = LoggerFactory.getLogger(WafInitialization.class);
logger.warn("Error initializing WAF library", e);
StandardizedLogging.libddwafCannotBeLoaded(logger, getLibc());
Expand Down
Loading