dd-trace
Version:
Datadog APM tracing client for JavaScript
178 lines (156 loc) • 7.69 kB
JavaScript
const log = require('../log')
const { updateConfig } = require('../telemetry')
const RemoteConfigCapabilities = require('../remote_config/capabilities')
const { setCollectionMode } = require('./user_tracking')
const Activation = require('./activation')
let autoUserInstrumModeId
let rc
/**
* Configures remote config handlers for appsec features
*
* @param {object} rcInstance - RemoteConfig instance
* @param {object} config - Tracer config
* @param {object} appsec - Appsec module
*/
function enable (rcInstance, config, appsec) {
rc = rcInstance
const activation = Activation.fromConfig(config)
if (activation !== Activation.DISABLED) {
if (activation === Activation.ONECLICK) {
rc.updateCapabilities(RemoteConfigCapabilities.ASM_ACTIVATION, true)
}
rc.updateCapabilities(RemoteConfigCapabilities.ASM_AUTO_USER_INSTRUM_MODE, true)
rc.setProductHandler('ASM_FEATURES', (action, rcConfig, configId) => {
if (!rcConfig) return
// this is put before other handlers because it can reject the config
if (typeof rcConfig.auto_user_instrum?.mode === 'string') {
if (action === 'apply' || action === 'modify') {
// check if there is already a config applied with this field
if (autoUserInstrumModeId && configId !== autoUserInstrumModeId) {
log.error('[RC] Multiple auto_user_instrum received in ASM_FEATURES. Discarding config')
// eslint-disable-next-line no-throw-literal
throw 'Multiple auto_user_instrum.mode received in ASM_FEATURES'
}
setCollectionMode(rcConfig.auto_user_instrum.mode)
autoUserInstrumModeId = configId
} else if (configId === autoUserInstrumModeId) {
setCollectionMode(config.appsec.eventTracking.mode)
autoUserInstrumModeId = null
}
}
if (activation === Activation.ONECLICK) {
enableOrDisableAppsec(action, rcConfig, config, appsec)
}
})
}
}
/**
* Enables or disables appsec based on remote config
*
* @param {string} action - 'apply', 'modify', or 'unapply'
* @param {object} rcConfig - Remote config
* @param {object} config - Tracer config
* @param {object} appsec - Appsec module
*/
function enableOrDisableAppsec (action, rcConfig, config, appsec) {
if (typeof rcConfig.asm?.enabled === 'boolean') {
const isRemoteConfigControlling = action === 'apply' || action === 'modify'
const shouldEnable = isRemoteConfigControlling
? rcConfig.asm.enabled // take control
: config.appsec.enabled // give back control to local config
if (shouldEnable) {
appsec.enable(config)
} else {
appsec.disable()
}
updateConfig([
{
name: 'appsec.enabled',
origin: isRemoteConfigControlling ? 'remote_config' : config.getOrigin('appsec.enabled'),
value: shouldEnable
}
], config)
}
}
/**
* Enables WAF update capabilities for remote config
*
* @param {object} appsecConfig - Appsec config
*/
function enableWafUpdate (appsecConfig) {
if (rc && appsecConfig && !appsecConfig.rules) {
// dirty require to make startup faster for serverless
const { ASM_WAF_PRODUCTS } = require('./rc-products')
const RuleManager = require('./rule_manager')
rc.updateCapabilities(RemoteConfigCapabilities.ASM_IP_BLOCKING, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_USER_BLOCKING, true)
// TODO: we should have a different capability for rule override
rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_RULES, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSIONS, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_REQUEST_BLOCKING, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RESPONSE_BLOCKING, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_RULES, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_BLOCKING_RESPONSE, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRUSTED_IPS, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_PROCESSOR_OVERRIDES, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_DATA_SCANNERS, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSION_DATA, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_ENDPOINT_FINGERPRINT, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_SESSION_FINGERPRINT, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_NETWORK_FINGERPRINT, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_HEADER_FINGERPRINT, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_MULTICONFIG, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRACE_TAGGING_RULES, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXTENDED_DATA_COLLECTION, true)
if (appsecConfig.rasp?.enabled) {
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SQLI, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SSRF, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_LFI, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SHI, true)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_CMDI, true)
}
rc.subscribeProducts(...ASM_WAF_PRODUCTS)
rc.setBatchHandler(ASM_WAF_PRODUCTS, RuleManager.updateWafFromRC)
}
}
/**
* Disables WAF update capabilities for remote config
*/
function disableWafUpdate () {
if (rc) {
const { ASM_WAF_PRODUCTS } = require('./rc-products')
const RuleManager = require('./rule_manager')
rc.updateCapabilities(RemoteConfigCapabilities.ASM_IP_BLOCKING, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_USER_BLOCKING, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_RULES, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSIONS, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_REQUEST_BLOCKING, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RESPONSE_BLOCKING, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_RULES, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_BLOCKING_RESPONSE, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRUSTED_IPS, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_PROCESSOR_OVERRIDES, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_DATA_SCANNERS, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSION_DATA, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_ENDPOINT_FINGERPRINT, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_SESSION_FINGERPRINT, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_NETWORK_FINGERPRINT, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_HEADER_FINGERPRINT, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_MULTICONFIG, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRACE_TAGGING_RULES, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXTENDED_DATA_COLLECTION, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SQLI, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SSRF, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_LFI, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SHI, false)
rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_CMDI, false)
rc.unsubscribeProducts(...ASM_WAF_PRODUCTS)
rc.removeBatchHandler(RuleManager.updateWafFromRC)
}
}
module.exports = {
enable,
enableWafUpdate,
disableWafUpdate
}