Skip to content

Commit

Permalink
New appsec headers collection (#4152)
Browse files Browse the repository at this point in the history
* change order of headers to match the spec so it's easier to compare

* add request identification headers collection

* update tests
  • Loading branch information
simon-id authored and juan-fernandez committed Mar 20, 2024
1 parent dc52efb commit 06b5aca
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 28 deletions.
35 changes: 24 additions & 11 deletions packages/dd-trace/src/appsec/reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,35 @@ let limiter = new Limiter(100)

const metricsQueue = new Map()

// following header lists are ordered in the same way the spec orders them, it doesn't matter but it's easier to compare
const contentHeaderList = [
'content-encoding',
'content-language',
'content-length',
'content-type'
'content-type',
'content-encoding',
'content-language'
]

const REQUEST_HEADERS_MAP = mapHeaderAndTags([
'accept',
'accept-encoding',
'accept-language',
'host',
...ipHeaderList,
'forwarded',
'user-agent',
'via',
'x-amzn-trace-id',
...contentHeaderList,
'host',
'user-agent',
'accept',
'accept-encoding',
'accept-language'
], 'http.request.headers.')

...ipHeaderList,
...contentHeaderList
const IDENTIFICATION_HEADERS_MAP = mapHeaderAndTags([
'x-amzn-trace-id',
'cloudfront-viewer-ja3-fingerprint',
'cf-ray',
'x-cloud-trace-context',
'x-appgw-trace-id',
'x-sigsci-requestid',
'x-sigsci-tags',
'akamai-user-risk'
], 'http.request.headers.')

const RESPONSE_HEADERS_MAP = mapHeaderAndTags(contentHeaderList, 'http.response.headers.')
Expand Down Expand Up @@ -171,6 +181,9 @@ function finishRequest (req, res) {

incrementWafRequestsMetric(req)

// collect some headers even when no attack is detected
rootSpan.addTags(filterHeaders(req.headers, IDENTIFICATION_HEADERS_MAP))

if (!rootSpan.context()._tags['appsec.event']) return

const newTags = filterHeaders(res.getHeaders(), RESPONSE_HEADERS_MAP)
Expand Down
51 changes: 34 additions & 17 deletions packages/dd-trace/test/appsec/reporter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,6 @@ describe('reporter', () => {
'network.client.ip': '8.8.8.8'
})
})

it('should include x-amzn-trace-id header', () => {
req.headers['x-amzn-trace-id'] = 'aws-id'

const result = Reporter.reportAttack('[{"rule":{},"rule_matches":[{}]}]')

expect(result).to.not.be.false
expect(span.addTags).to.have.been.calledOnce
expect(span.addTags.firstCall.args[0]).to.not.undefined
expect(span.addTags.firstCall.args[0]['http.request.headers.x-amzn-trace-id']).to.be.eq('aws-id')
})
})

describe('reportWafUpdate', () => {
Expand Down Expand Up @@ -360,22 +349,46 @@ describe('reporter', () => {
Reporter.finishRequest(req, wafContext, {})

expect(web.root).to.have.been.calledOnceWithExactly(req)
expect(span.addTags).to.have.been.calledOnceWithExactly({ a: 1, b: 2 })
expect(span.addTags).to.have.been.calledWithExactly({ a: 1, b: 2 })
expect(Reporter.metricsQueue).to.be.empty
})

it('should not add http response data when no attack was previously found', () => {
const req = {}
it('should only add identification headers when no attack was previously found', () => {
const req = {
headers: {
'not-included': 'hello',
'x-amzn-trace-id': 'a',
'cloudfront-viewer-ja3-fingerprint': 'b',
'cf-ray': 'c',
'x-cloud-trace-context': 'd',
'x-appgw-trace-id': 'e',
'x-sigsci-requestid': 'f',
'x-sigsci-tags': 'g',
'akamai-user-risk': 'h'
}
}

Reporter.finishRequest(req)
expect(web.root).to.have.been.calledOnceWith(req)
expect(span.addTags).to.not.have.been.called
expect(span.addTags).to.have.been.calledOnceWithExactly({
'http.request.headers.x-amzn-trace-id': 'a',
'http.request.headers.cloudfront-viewer-ja3-fingerprint': 'b',
'http.request.headers.cf-ray': 'c',
'http.request.headers.x-cloud-trace-context': 'd',
'http.request.headers.x-appgw-trace-id': 'e',
'http.request.headers.x-sigsci-requestid': 'f',
'http.request.headers.x-sigsci-tags': 'g',
'http.request.headers.akamai-user-risk': 'h'
})
})

it('should add http response data inside request span', () => {
const req = {
route: {
path: '/path/:param'
},
headers: {
'x-cloud-trace-context': 'd'
}
}

Expand All @@ -393,7 +406,11 @@ describe('reporter', () => {
Reporter.finishRequest(req, res)
expect(web.root).to.have.been.calledOnceWith(req)

expect(span.addTags).to.have.been.calledOnceWithExactly({
expect(span.addTags).to.have.been.calledTwice
expect(span.addTags.firstCall).to.have.been.calledWithExactly({
'http.request.headers.x-cloud-trace-context': 'd'
})
expect(span.addTags.secondCall).to.have.been.calledWithExactly({
'http.response.headers.content-type': 'application/json',
'http.response.headers.content-length': '42',
'http.endpoint': '/path/:param'
Expand All @@ -416,7 +433,7 @@ describe('reporter', () => {
Reporter.finishRequest(req, res)
expect(web.root).to.have.been.calledOnceWith(req)

expect(span.addTags).to.have.been.calledOnceWithExactly({
expect(span.addTags).to.have.been.calledWithExactly({
'http.response.headers.content-type': 'application/json',
'http.response.headers.content-length': '42'
})
Expand Down

0 comments on commit 06b5aca

Please sign in to comment.