dd-trace
Version:
Datadog APM tracing client for JavaScript
159 lines (131 loc) • 7.04 kB
JavaScript
const Activation = require('../appsec/activation')
const RemoteConfigManager = require('./manager')
const RemoteConfigCapabilities = require('./capabilities')
const { setCollectionMode } = require('../appsec/user_tracking')
const log = require('../log')
let rc
function enable (config, appsec) {
rc = new RemoteConfigManager(config)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_HTTP_HEADER_TAGS, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_LOGS_INJECTION, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLED, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RULES, true)
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)
let autoUserInstrumModeId
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)
}
})
}
return rc
}
function enableOrDisableAppsec (action, rcConfig, config, appsec) {
if (typeof rcConfig.asm?.enabled === 'boolean') {
const shouldEnable = action === 'apply' || action === 'modify'
? rcConfig.asm.enabled // take control
: config.appsec.enabled // give back control to local config
if (shouldEnable) {
appsec.enable(config)
} else {
appsec.disable()
}
}
}
// TODO: all appsec specific stuff should be moved back in the appsec folder
function enableWafUpdate (appsecConfig) {
if (rc && appsecConfig && !appsecConfig.rules) {
// dirty require to make startup faster for serverless
const RuleManager = require('../appsec/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_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)
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)
}
// TODO: delete noop handlers and kPreUpdate and replace with batched handlers
rc.setProductHandler('ASM_DATA', noop)
rc.setProductHandler('ASM_DD', noop)
rc.setProductHandler('ASM', noop)
rc.on(RemoteConfigManager.kPreUpdate, RuleManager.updateWafFromRC)
}
}
function disableWafUpdate () {
if (rc) {
const RuleManager = require('../appsec/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_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_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.removeProductHandler('ASM_DATA')
rc.removeProductHandler('ASM_DD')
rc.removeProductHandler('ASM')
rc.off(RemoteConfigManager.kPreUpdate, RuleManager.updateWafFromRC)
}
}
function noop () {}
module.exports = {
enable,
enableWafUpdate,
disableWafUpdate
}