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

Embed AppSec rules and templates files to be compatible with bundlers #2913

Merged
merged 18 commits into from
Mar 31, 2023
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
@@ -1,4 +1,7 @@
<!-- Sorry, you’ve been blocked -->
/* eslint-disable max-len */
'use strict'

const html = `<!-- Sorry, you've been blocked -->
<!DOCTYPE html>
<html lang="en">

Expand Down Expand Up @@ -97,3 +100,18 @@
</body>

</html>
`

const json = `{
"errors": [
{
"title": "You've been blocked",
"detail": "Sorry, you cannot access this page. Please contact the customer service team. Security provided by Datadog."
}
]
}`

module.exports = {
html,
json
}
33 changes: 9 additions & 24 deletions packages/dd-trace/src/appsec/blocking.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
'use strict'

const log = require('../log')
const fs = require('fs')
const blockedTemplates = require('./blocked_templates')

// TODO: move template loading to a proper spot.
let templateLoaded = false
let templateHtml = ''
let templateJson = ''
let templateHtml = blockedTemplates.html
let templateJson = blockedTemplates.json

function block (req, res, rootSpan, abortController) {
if (res.headersSent) {
Expand Down Expand Up @@ -42,29 +40,16 @@ function block (req, res, rootSpan, abortController) {
}
}

function loadTemplates (config) {
if (!templateLoaded) {
templateHtml = fs.readFileSync(config.appsec.blockedTemplateHtml)
templateJson = fs.readFileSync(config.appsec.blockedTemplateJson)
templateLoaded = true
function setTemplates (config) {
if (config.appsec.blockedTemplateHtml) {
templateHtml = config.appsec.blockedTemplateHtml
}
}

async function loadTemplatesAsync (config) {
if (!templateLoaded) {
templateHtml = await fs.promises.readFile(config.appsec.blockedTemplateHtml)
templateJson = await fs.promises.readFile(config.appsec.blockedTemplateJson)
templateLoaded = true
if (config.appsec.blockedTemplateJson) {
templateJson = config.appsec.blockedTemplateJson
}
}

function resetTemplates () {
templateLoaded = false
}

module.exports = {
block,
loadTemplates,
loadTemplatesAsync,
resetTemplates
setTemplates
}
22 changes: 4 additions & 18 deletions packages/dd-trace/src/appsec/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use strict'

const fs = require('fs')
const path = require('path')
const log = require('../log')
const RuleManager = require('./rule_manager')
const remoteConfig = require('./remote_config')
Expand All @@ -12,7 +10,7 @@ const Reporter = require('./reporter')
const web = require('../plugins/util/web')
const { extractIp } = require('../plugins/util/ip_extractor')
const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
const { block, loadTemplates, loadTemplatesAsync } = require('./blocking')
const { block, setTemplates } = require('./blocking')

let isEnabled = false
let config
Expand All @@ -21,21 +19,10 @@ function enable (_config) {
if (isEnabled) return

try {
loadTemplates(_config)
const rules = fs.readFileSync(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
enableFromRules(_config, JSON.parse(rules))
} catch (err) {
abortEnable(err)
}
}
setTemplates(_config)

async function enableAsync (_config) {
if (isEnabled) return

try {
await loadTemplatesAsync(_config)
const rules = await fs.promises.readFile(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
enableFromRules(_config, JSON.parse(rules))
const rules = _config.appsec.rules || require('./recommended.json')
enableFromRules(_config, rules)
} catch (err) {
abortEnable(err)
}
Expand Down Expand Up @@ -169,7 +156,6 @@ function disable () {

module.exports = {
enable,
enableAsync,
disable,
incomingHttpStartTranslator,
incomingHttpEndTranslator
Expand Down
2 changes: 1 addition & 1 deletion packages/dd-trace/src/appsec/remote_config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function enable (config) {
}

if (shouldEnable) {
require('..').enableAsync(config).catch(() => {})
require('..').enable(config)
} else {
require('..').disable()
}
Expand Down
4 changes: 2 additions & 2 deletions packages/dd-trace/src/appsec/sdk/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

const { trackUserLoginSuccessEvent, trackUserLoginFailureEvent, trackCustomEvent } = require('./track_event')
const { checkUserAndSetUser, blockRequest } = require('./user_blocking')
const { loadTemplates } = require('../blocking')
const { setTemplates } = require('../blocking')
const { setUser } = require('./set_user')

class AppsecSdk {
constructor (tracer, config) {
this._tracer = tracer
if (config) {
loadTemplates(config)
setTemplates(config)
}
}

Expand Down
8 changes: 0 additions & 8 deletions packages/dd-trace/src/appsec/templates/blocked.json

This file was deleted.

26 changes: 7 additions & 19 deletions packages/dd-trace/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const coalesce = require('koalas')
const tagger = require('./tagger')
const { isTrue, isFalse } = require('./util')
const uuid = require('crypto-randomuuid')
const path = require('path')

const fromEntries = Object.fromEntries || (entries =>
entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
Expand All @@ -22,16 +21,7 @@ function maybeFile (filepath) {
try {
return fs.readFileSync(filepath, 'utf8')
} catch (e) {
return undefined
}
}

function maybePath (filepath) {
if (!filepath) return
try {
fs.openSync(filepath, 'r')
return filepath
} catch (e) {
log.error(e)
return undefined
}
}
Expand Down Expand Up @@ -298,8 +288,8 @@ class Config {
)

const DD_APPSEC_RULES = coalesce(
appsec.rules,
process.env.DD_APPSEC_RULES
safeJsonParse(maybeFile(appsec.rules)),
safeJsonParse(maybeFile(process.env.DD_APPSEC_RULES))
)
const DD_APPSEC_TRACE_RATE_LIMIT = coalesce(
parseInt(appsec.rateLimit),
Expand All @@ -326,14 +316,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
)
const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML = coalesce(
maybePath(appsec.blockedTemplateHtml),
maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML),
path.join(__dirname, 'appsec', 'templates', 'blocked.html')
maybeFile(appsec.blockedTemplateHtml),
maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML)
)
const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON = coalesce(
maybePath(appsec.blockedTemplateJson),
maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON),
path.join(__dirname, 'appsec', 'templates', 'blocked.json')
maybeFile(appsec.blockedTemplateJson),
maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
)

const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
Expand Down
Loading