Skip to content

Commit 0e39cd5

Browse files
author
Anthony Rizzo
committed
feat: add csp-violation-event-plugin
1 parent f99498c commit 0e39cd5

12 files changed

+630
-8
lines changed

app/csp_violation_event.html

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>RUM Integ Test</title>
5+
<script src="./loader_csp_violation_event.js"></script>
6+
<link
7+
rel="icon"
8+
type="image/png"
9+
href="https://awsmedia.s3.amazonaws.com/favicon.ico"
10+
/>
11+
12+
<script>
13+
// Common to all test pages
14+
function dispatch() {
15+
cwr('dispatch');
16+
}
17+
18+
function clearRequestResponse() {
19+
document.getElementById('request_url').innerText = '';
20+
document.getElementById('request_header').innerText = '';
21+
document.getElementById('request_body').innerText = '';
22+
23+
document.getElementById('response_status').innerText = '';
24+
document.getElementById('response_header').innerText = '';
25+
document.getElementById('response_body').innerText = '';
26+
}
27+
28+
// Specific to ContentSecurityPolicy Violation error plugin
29+
function triggerSecurityPolicyViolationEvent() {
30+
const event = new Event('securitypolicyviolation');
31+
Object.assign(event, {
32+
violatedDirective: 'test:violatedDirective',
33+
documentURI: 'http://documentURI',
34+
blockedURI: 'https://blockedURI',
35+
originalPolicy: 'test:originalPolicy',
36+
referrer: 'test:referrer',
37+
statusCode: 200,
38+
effectiveDirective: 'test:effectiveDirective'
39+
});
40+
dispatchEvent(event);
41+
}
42+
43+
function recordCspViolationEvent() {
44+
const event = new Event('securitypolicyviolation');
45+
Object.assign(event, {
46+
violatedDirective: 'test:violatedDirective',
47+
documentURI: 'http://documentURI',
48+
blockedURI: 'https://blockedURI',
49+
originalPolicy: 'test:originalPolicy',
50+
referrer: 'test:referrer',
51+
statusCode: 200,
52+
effectiveDirective: 'test:effectiveDirective'
53+
});
54+
55+
cwr('recordCspViolation', event);
56+
}
57+
58+
function triggerIgnoredSecurityPolicyViolationEvent() {
59+
const event = new Event('securitypolicyviolation');
60+
Object.assign(event, {
61+
violatedDirective: 'test:violatedDirective',
62+
documentURI: 'http://ignoredDocumentURI',
63+
blockedURI: 'https://blockedURI',
64+
originalPolicy: 'test:originalPolicy',
65+
referrer: 'test:referrer',
66+
statusCode: 200,
67+
effectiveDirective: 'test:effectiveDirective'
68+
});
69+
dispatchEvent(event);
70+
}
71+
72+
function disable() {
73+
cwr('disable');
74+
}
75+
76+
function enable() {
77+
cwr('enable');
78+
}
79+
</script>
80+
81+
<style>
82+
table {
83+
border-collapse: collapse;
84+
margin-top: 10px;
85+
margin-bottom: 10px;
86+
}
87+
88+
td,
89+
th {
90+
border: 1px solid black;
91+
text-align: left;
92+
padding: 8px;
93+
}
94+
</style>
95+
</head>
96+
<body>
97+
<p id="welcome">This application is used for RUM integ testing.</p>
98+
<hr />
99+
<button
100+
id="triggerSecurityPolicyViolationEvent"
101+
onclick="triggerSecurityPolicyViolationEvent()"
102+
>
103+
Trigger SecurityPolicyViolationEvent
104+
</button>
105+
<button
106+
id="triggerIgnoredSecurityPolicyViolationEvent"
107+
onclick="triggerIgnoredSecurityPolicyViolationEvent()"
108+
>
109+
Trigger IgnoredSecurityPolicyViolationEvent
110+
</button>
111+
<button
112+
id="recordCspViolationEvent"
113+
onclick="recordCspViolationEvent()"
114+
>
115+
Record CspViolationEvent
116+
</button>
117+
<button id="disable" onclick="disable()">Disable</button>
118+
<button id="enable" onclick="enable()">Enable</button>
119+
<hr />
120+
<button id="dispatch" onclick="dispatch()">Dispatch</button>
121+
<button id="clearRequestResponse" onclick="clearRequestResponse()">
122+
Clear
123+
</button>
124+
<hr />
125+
<span id="request"></span>
126+
<span id="response"></span>
127+
<table>
128+
<tr>
129+
<td>Request URL</td>
130+
<td id="request_url"></td>
131+
</tr>
132+
<tr>
133+
<td>Request Header</td>
134+
<td id="request_header"></td>
135+
</tr>
136+
<tr>
137+
<td>Request Body</td>
138+
<td id="request_body"></td>
139+
</tr>
140+
</table>
141+
<table>
142+
<tr>
143+
<td>Response Status Code</td>
144+
<td id="response_status"></td>
145+
</tr>
146+
<tr>
147+
<td>Response Header</td>
148+
<td id="response_header"></td>
149+
</tr>
150+
<tr>
151+
<td>Response Body</td>
152+
<td id="response_body"></td>
153+
</tr>
154+
</table>
155+
</body>
156+
</html>

package-lock.json

+10-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/CommandQueue.ts

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface CommandFunctions {
1414
addSessionAttributes: CommandFunction;
1515
recordPageView: CommandFunction;
1616
recordError: CommandFunction;
17+
recordCspViolation: CommandFunction;
1718
registerDomEvents: CommandFunction;
1819
recordEvent: CommandFunction;
1920
dispatch: CommandFunction;
@@ -68,6 +69,9 @@ export class CommandQueue {
6869
recordError: (payload: any): void => {
6970
this.orchestration.recordError(payload);
7071
},
72+
recordCspViolation: (payload: any): void => {
73+
this.orchestration.recordCspViolation(payload);
74+
},
7175
registerDomEvents: (payload: any): void => {
7276
this.orchestration.registerDomEvents(payload);
7377
},
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"$id": "com.amazon.rum.csp_violation_event",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"title": "CspViolationEvent",
5+
"type": "object",
6+
"properties": {
7+
"version": {
8+
"const": "1.0.0",
9+
"type": "string",
10+
"description": "Schema version."
11+
},
12+
"blockedURI": {
13+
"type": "string",
14+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/blockedURI"
15+
},
16+
"columnNumber": {
17+
"type": "number",
18+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/columnNumber"
19+
},
20+
"disposition": {
21+
"type": "string",
22+
"enum": ["enforce", "report"],
23+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/disposition"
24+
},
25+
"documentURI": {
26+
"type": "string",
27+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/documentURI"
28+
},
29+
"effectiveDirective": {
30+
"type": "string",
31+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/effectiveDirective"
32+
},
33+
"lineNumber": {
34+
"type": "number",
35+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/lineNumber"
36+
},
37+
"originalPolicy": {
38+
"type": "string",
39+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/originalPolicy"
40+
},
41+
"referrer": {
42+
"type": ["string", "null"],
43+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/referrer"
44+
},
45+
"sample": {
46+
"type": "string",
47+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/sample"
48+
},
49+
"sourceFile": {
50+
"type": ["string", "null"],
51+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/sourceFile"
52+
},
53+
"statusCode": {
54+
"type": "number",
55+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/statusCode"
56+
},
57+
"violatedDirective": {
58+
"type": "string",
59+
"description": "https://developer.mozilla.org/docs/Web/API/SecurityPolicyViolationEvent/violatedDirective"
60+
}
61+
},
62+
"additionalProperties": false,
63+
"required": ["version"]
64+
}

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export { PageAttributes } from './sessions/PageManager';
1212
export { Plugin } from './plugins/Plugin';
1313
export { PluginContext } from './plugins/types';
1414
export { TTIPlugin } from './plugins/event-plugins/TTIPlugin';
15+
export * from './plugins/event-plugins/CspViolationPlugin';
1516
export * from './plugins/event-plugins/DomEventPlugin';
1617
export * from './plugins/event-plugins/JsErrorPlugin';
1718
export * from './plugins/event-plugins/NavigationPlugin';
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { loader } from './loader';
2+
import { showRequestClientBuilder } from '../test-utils/mock-http-handler';
3+
import { CspViolationPlugin } from '../plugins/event-plugins/CspViolationPlugin';
4+
loader('cwr', 'abc123', '1.0', 'us-west-2', './rum_javascript_telemetry.js', {
5+
allowCookies: true,
6+
dispatchInterval: 0,
7+
metaDataPluginsToLoad: [],
8+
eventPluginsToLoad: [
9+
new CspViolationPlugin({
10+
ignore: (e) => {
11+
const ignoredDocuments = ['http://ignoredDocumentURI'];
12+
return ignoredDocuments.includes(e.documentURI);
13+
}
14+
})
15+
],
16+
telemetries: [],
17+
clientBuilder: showRequestClientBuilder
18+
});
19+
window.cwr('setAwsCredentials', {
20+
accessKeyId: 'a',
21+
secretAccessKey: 'b',
22+
sessionToken: 'c'
23+
});

src/orchestration/Orchestration.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import {
1313
JsErrorPlugin,
1414
JS_ERROR_EVENT_PLUGIN_ID
1515
} from '../plugins/event-plugins/JsErrorPlugin';
16+
import {
17+
CspViolationPlugin,
18+
CSP_VIOLATION_EVENT_PLUGIN_ID
19+
} from '../plugins/event-plugins/CspViolationPlugin';
20+
1621
import { EventCache } from '../event-cache/EventCache';
1722
import { ClientBuilder, Dispatch } from '../dispatch/Dispatch';
1823
import {
@@ -342,6 +347,20 @@ export class Orchestration {
342347
this.pluginManager.record(JS_ERROR_EVENT_PLUGIN_ID, error);
343348
}
344349

350+
/**
351+
* Record an SecurityPolicyViolationEvent using the CSP Violation plugin.
352+
*
353+
* @param securityPolicyViolationEvent a SecurityPolicyViolationEvent.
354+
*/
355+
public recordCspViolation(
356+
securityPolicyViolationEvent: SecurityPolicyViolationEvent
357+
) {
358+
this.pluginManager.record(
359+
CSP_VIOLATION_EVENT_PLUGIN_ID,
360+
securityPolicyViolationEvent
361+
);
362+
}
363+
345364
/**
346365
* Update DOM plugin to record the (additional) provided DOM events.
347366
*
@@ -464,7 +483,6 @@ export class Orchestration {
464483
];
465484
}
466485
});
467-
468486
return plugins;
469487
}
470488

@@ -484,7 +502,10 @@ export class Orchestration {
484502
private telemetryFunctor(): TelemetriesFunctor {
485503
return {
486504
[TelemetryEnum.Errors]: (config: object): InternalPlugin[] => {
487-
return [new JsErrorPlugin(config)];
505+
return [
506+
new JsErrorPlugin(config),
507+
new CspViolationPlugin(config)
508+
];
488509
},
489510
[TelemetryEnum.Performance]: (config: object): InternalPlugin[] => {
490511
return [

0 commit comments

Comments
 (0)