@aligent/cdk-header-change-detection 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +2 -0
- package/index.js +6 -0
- package/lib/header-change-detection.d.ts +38 -0
- package/lib/header-change-detection.js +76 -0
- package/lib/lambda/header-check.d.ts +1 -0
- package/lib/lambda/header-check.js +267 -0
- package/package.json +33 -0
package/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HeaderChangeDetection = void 0;
|
|
4
|
+
const header_change_detection_1 = require("./lib/header-change-detection");
|
|
5
|
+
Object.defineProperty(exports, "HeaderChangeDetection", { enumerable: true, get: function () { return header_change_detection_1.HeaderChangeDetection; } });
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9wYWNrYWdlcy9oZWFkZXItY2hhbmdlLWRldGVjdGlvbi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyRUFHdUM7QUFFOUIsc0dBSlAsK0NBQXFCLE9BSU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBIZWFkZXJDaGFuZ2VEZXRlY3Rpb24sXG4gIEhlYWRlckNoYW5nZURldGVjdGlvblByb3BzLFxufSBmcm9tIFwiLi9saWIvaGVhZGVyLWNoYW5nZS1kZXRlY3Rpb25cIjtcblxuZXhwb3J0IHsgSGVhZGVyQ2hhbmdlRGV0ZWN0aW9uLCBIZWFkZXJDaGFuZ2VEZXRlY3Rpb25Qcm9wcyB9O1xuIl19
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RuleProps, Schedule } from "aws-cdk-lib/aws-events";
|
|
2
|
+
import { SnsTopic } from "aws-cdk-lib/aws-events-targets";
|
|
3
|
+
import { Construct } from "constructs";
|
|
4
|
+
export interface HeaderChangeDetectionProps {
|
|
5
|
+
/**
|
|
6
|
+
* List of URLs to monitor for header changes
|
|
7
|
+
*/
|
|
8
|
+
urls: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Optional list of additional headers to monitor
|
|
11
|
+
*
|
|
12
|
+
* @default []
|
|
13
|
+
*/
|
|
14
|
+
additionalHeaders?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Optionally disable all the default headers
|
|
17
|
+
*
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
disableDefaults?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* SNS Topic to send change detection notifications to
|
|
23
|
+
*/
|
|
24
|
+
snsTopic: SnsTopic;
|
|
25
|
+
/**
|
|
26
|
+
* The schedule for performing the header check
|
|
27
|
+
*
|
|
28
|
+
* @default Schedule.rate(Duration.hours(1))
|
|
29
|
+
*/
|
|
30
|
+
schedule?: Schedule;
|
|
31
|
+
/**
|
|
32
|
+
* Optionally pass any rule properties
|
|
33
|
+
*/
|
|
34
|
+
ruleProps?: Partial<RuleProps>;
|
|
35
|
+
}
|
|
36
|
+
export declare class HeaderChangeDetection extends Construct {
|
|
37
|
+
constructor(scope: Construct, id: string, props: HeaderChangeDetectionProps);
|
|
38
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HeaderChangeDetection = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
|
|
6
|
+
const aws_events_1 = require("aws-cdk-lib/aws-events");
|
|
7
|
+
const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets");
|
|
8
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
9
|
+
const constructs_1 = require("constructs");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const cdk_esbuild_1 = require("@aligent/cdk-esbuild");
|
|
12
|
+
const command = [
|
|
13
|
+
"sh",
|
|
14
|
+
"-c",
|
|
15
|
+
'echo "Docker build not supported. Please install esbuild."',
|
|
16
|
+
];
|
|
17
|
+
const defaultHeaders = [
|
|
18
|
+
"content-security-policy",
|
|
19
|
+
"content-security-policy-report-only",
|
|
20
|
+
"reporting-endpoints",
|
|
21
|
+
"strict-transport-security",
|
|
22
|
+
"x-frame-options",
|
|
23
|
+
"x-content-type-options",
|
|
24
|
+
"cross-origin-opener-policy",
|
|
25
|
+
"cross-origin-embedder-policy",
|
|
26
|
+
"cross-origin-resource-policy",
|
|
27
|
+
"referrer-policy",
|
|
28
|
+
"permission-policy",
|
|
29
|
+
"cache-control",
|
|
30
|
+
"set-cookie",
|
|
31
|
+
];
|
|
32
|
+
class HeaderChangeDetection extends constructs_1.Construct {
|
|
33
|
+
constructor(scope, id, props) {
|
|
34
|
+
var _a;
|
|
35
|
+
super(scope, id);
|
|
36
|
+
const headers = props.disableDefaults ? [] : defaultHeaders;
|
|
37
|
+
headers.push(...(((_a = props.additionalHeaders) === null || _a === void 0 ? void 0 : _a.map(header => header.toLowerCase())) || []));
|
|
38
|
+
const table = new aws_dynamodb_1.Table(this, "Table", {
|
|
39
|
+
partitionKey: {
|
|
40
|
+
name: "Url",
|
|
41
|
+
type: aws_dynamodb_1.AttributeType.STRING,
|
|
42
|
+
},
|
|
43
|
+
billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
|
|
44
|
+
});
|
|
45
|
+
const schedule = new aws_events_1.Rule(this, "EventRule", {
|
|
46
|
+
schedule: props.schedule || aws_events_1.Schedule.rate(aws_cdk_lib_1.Duration.hours(1)),
|
|
47
|
+
...props.ruleProps,
|
|
48
|
+
});
|
|
49
|
+
const lambda = new aws_lambda_1.Function(this, "HeaderCheck", {
|
|
50
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
51
|
+
runtime: aws_lambda_1.Runtime.NODEJS_20_X,
|
|
52
|
+
handler: "header-check.handler",
|
|
53
|
+
code: aws_lambda_1.Code.fromAsset((0, path_1.join)(__dirname, "lambda"), {
|
|
54
|
+
bundling: {
|
|
55
|
+
command,
|
|
56
|
+
image: aws_cdk_lib_1.DockerImage.fromRegistry("busybox"),
|
|
57
|
+
local: new cdk_esbuild_1.Esbuild({
|
|
58
|
+
entryPoints: [(0, path_1.join)(__dirname, "lambda/header-check.ts")],
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
environment: {
|
|
63
|
+
URLS: props.urls.join(","),
|
|
64
|
+
HEADERS: headers.join(","),
|
|
65
|
+
TABLE: table.tableName,
|
|
66
|
+
TOPIC_ARN: props.snsTopic.topic.topicArn,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
schedule.addTarget(new aws_events_targets_1.LambdaFunction(lambda));
|
|
70
|
+
table.grantWriteData(lambda);
|
|
71
|
+
table.grantReadData(lambda);
|
|
72
|
+
props.snsTopic.topic.grantPublish(lambda);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.HeaderChangeDetection = HeaderChangeDetection;
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVyLWNoYW5nZS1kZXRlY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wYWNrYWdlcy9oZWFkZXItY2hhbmdlLWRldGVjdGlvbi9saWIvaGVhZGVyLWNoYW5nZS1kZXRlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQW9EO0FBQ3BELDJEQUE2RTtBQUM3RSx1REFBbUU7QUFDbkUsdUVBQTBFO0FBQzFFLHVEQUErRTtBQUMvRSwyQ0FBdUM7QUFDdkMsK0JBQTRCO0FBQzVCLHNEQUErQztBQXdDL0MsTUFBTSxPQUFPLEdBQUc7SUFDZCxJQUFJO0lBQ0osSUFBSTtJQUNKLDREQUE0RDtDQUM3RCxDQUFDO0FBRUYsTUFBTSxjQUFjLEdBQUc7SUFDckIseUJBQXlCO0lBQ3pCLHFDQUFxQztJQUNyQyxxQkFBcUI7SUFDckIsMkJBQTJCO0lBQzNCLGlCQUFpQjtJQUNqQix3QkFBd0I7SUFDeEIsNEJBQTRCO0lBQzVCLDhCQUE4QjtJQUM5Qiw4QkFBOEI7SUFDOUIsaUJBQWlCO0lBQ2pCLG1CQUFtQjtJQUNuQixlQUFlO0lBQ2YsWUFBWTtDQUNiLENBQUM7QUFFRixNQUFhLHFCQUFzQixTQUFRLHNCQUFTO0lBQ2xELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBaUM7O1FBQ3pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUM7UUFFNUQsT0FBTyxDQUFDLElBQUksQ0FDVixHQUFHLENBQUMsQ0FBQSxNQUFBLEtBQUssQ0FBQyxpQkFBaUIsMENBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUksRUFBRSxDQUFDLENBQ3hFLENBQUM7UUFFRixNQUFNLEtBQUssR0FBRyxJQUFJLG9CQUFLLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRTtZQUNyQyxZQUFZLEVBQUU7Z0JBQ1osSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsSUFBSSxFQUFFLDRCQUFhLENBQUMsTUFBTTthQUMzQjtZQUNELFdBQVcsRUFBRSwwQkFBVyxDQUFDLGVBQWU7U0FDekMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxRQUFRLEdBQUcsSUFBSSxpQkFBSSxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUU7WUFDM0MsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLElBQUkscUJBQVEsQ0FBQyxJQUFJLENBQUMsc0JBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUQsR0FBRyxLQUFLLENBQUMsU0FBUztTQUNuQixDQUFDLENBQUM7UUFFSCxNQUFNLE1BQU0sR0FBRyxJQUFJLHFCQUFRLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUMvQyxZQUFZLEVBQUUseUJBQVksQ0FBQyxNQUFNO1lBQ2pDLE9BQU8sRUFBRSxvQkFBTyxDQUFDLFdBQVc7WUFDNUIsT0FBTyxFQUFFLHNCQUFzQjtZQUMvQixJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQUMsSUFBQSxXQUFJLEVBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxFQUFFO2dCQUM5QyxRQUFRLEVBQUU7b0JBQ1IsT0FBTztvQkFDUCxLQUFLLEVBQUUseUJBQVcsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO29CQUMxQyxLQUFLLEVBQUUsSUFBSSxxQkFBTyxDQUFDO3dCQUNqQixXQUFXLEVBQUUsQ0FBQyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztxQkFDekQsQ0FBQztpQkFDSDthQUNGLENBQUM7WUFDRixXQUFXLEVBQUU7Z0JBQ1gsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDMUIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO2dCQUMxQixLQUFLLEVBQUUsS0FBSyxDQUFDLFNBQVM7Z0JBQ3RCLFNBQVMsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRO2FBQ3pDO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLG1DQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUUvQyxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdCLEtBQUssQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUIsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLENBQUM7Q0FDRjtBQWxERCxzREFrREMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEb2NrZXJJbWFnZSwgRHVyYXRpb24gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IEF0dHJpYnV0ZVR5cGUsIEJpbGxpbmdNb2RlLCBUYWJsZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGJcIjtcbmltcG9ydCB7IFJ1bGUsIFJ1bGVQcm9wcywgU2NoZWR1bGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWV2ZW50c1wiO1xuaW1wb3J0IHsgTGFtYmRhRnVuY3Rpb24sIFNuc1RvcGljIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0c1wiO1xuaW1wb3J0IHsgQXJjaGl0ZWN0dXJlLCBDb2RlLCBGdW5jdGlvbiwgUnVudGltZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBFc2J1aWxkIH0gZnJvbSBcIkBhbGlnZW50L2Nkay1lc2J1aWxkXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGVhZGVyQ2hhbmdlRGV0ZWN0aW9uUHJvcHMge1xuICAvKipcbiAgICogTGlzdCBvZiBVUkxzIHRvIG1vbml0b3IgZm9yIGhlYWRlciBjaGFuZ2VzXG4gICAqL1xuICB1cmxzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogT3B0aW9uYWwgbGlzdCBvZiBhZGRpdGlvbmFsIGhlYWRlcnMgdG8gbW9uaXRvclxuICAgKlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgYWRkaXRpb25hbEhlYWRlcnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogT3B0aW9uYWxseSBkaXNhYmxlIGFsbCB0aGUgZGVmYXVsdCBoZWFkZXJzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBkaXNhYmxlRGVmYXVsdHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTTlMgVG9waWMgdG8gc2VuZCBjaGFuZ2UgZGV0ZWN0aW9uIG5vdGlmaWNhdGlvbnMgdG9cbiAgICovXG4gIHNuc1RvcGljOiBTbnNUb3BpYztcblxuICAvKipcbiAgICogVGhlIHNjaGVkdWxlIGZvciBwZXJmb3JtaW5nIHRoZSBoZWFkZXIgY2hlY2tcbiAgICpcbiAgICogQGRlZmF1bHQgU2NoZWR1bGUucmF0ZShEdXJhdGlvbi5ob3VycygxKSlcbiAgICovXG4gIHNjaGVkdWxlPzogU2NoZWR1bGU7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsbHkgcGFzcyBhbnkgcnVsZSBwcm9wZXJ0aWVzXG4gICAqL1xuICBydWxlUHJvcHM/OiBQYXJ0aWFsPFJ1bGVQcm9wcz47XG59XG5cbmNvbnN0IGNvbW1hbmQgPSBbXG4gIFwic2hcIixcbiAgXCItY1wiLFxuICAnZWNobyBcIkRvY2tlciBidWlsZCBub3Qgc3VwcG9ydGVkLiBQbGVhc2UgaW5zdGFsbCBlc2J1aWxkLlwiJyxcbl07XG5cbmNvbnN0IGRlZmF1bHRIZWFkZXJzID0gW1xuICBcImNvbnRlbnQtc2VjdXJpdHktcG9saWN5XCIsXG4gIFwiY29udGVudC1zZWN1cml0eS1wb2xpY3ktcmVwb3J0LW9ubHlcIixcbiAgXCJyZXBvcnRpbmctZW5kcG9pbnRzXCIsXG4gIFwic3RyaWN0LXRyYW5zcG9ydC1zZWN1cml0eVwiLFxuICBcIngtZnJhbWUtb3B0aW9uc1wiLFxuICBcIngtY29udGVudC10eXBlLW9wdGlvbnNcIixcbiAgXCJjcm9zcy1vcmlnaW4tb3BlbmVyLXBvbGljeVwiLFxuICBcImNyb3NzLW9yaWdpbi1lbWJlZGRlci1wb2xpY3lcIixcbiAgXCJjcm9zcy1vcmlnaW4tcmVzb3VyY2UtcG9saWN5XCIsXG4gIFwicmVmZXJyZXItcG9saWN5XCIsXG4gIFwicGVybWlzc2lvbi1wb2xpY3lcIixcbiAgXCJjYWNoZS1jb250cm9sXCIsXG4gIFwic2V0LWNvb2tpZVwiLFxuXTtcblxuZXhwb3J0IGNsYXNzIEhlYWRlckNoYW5nZURldGVjdGlvbiBleHRlbmRzIENvbnN0cnVjdCB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBIZWFkZXJDaGFuZ2VEZXRlY3Rpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBoZWFkZXJzID0gcHJvcHMuZGlzYWJsZURlZmF1bHRzID8gW10gOiBkZWZhdWx0SGVhZGVycztcblxuICAgIGhlYWRlcnMucHVzaChcbiAgICAgIC4uLihwcm9wcy5hZGRpdGlvbmFsSGVhZGVycz8ubWFwKGhlYWRlciA9PiBoZWFkZXIudG9Mb3dlckNhc2UoKSkgfHwgW10pXG4gICAgKTtcblxuICAgIGNvbnN0IHRhYmxlID0gbmV3IFRhYmxlKHRoaXMsIFwiVGFibGVcIiwge1xuICAgICAgcGFydGl0aW9uS2V5OiB7XG4gICAgICAgIG5hbWU6IFwiVXJsXCIsXG4gICAgICAgIHR5cGU6IEF0dHJpYnV0ZVR5cGUuU1RSSU5HLFxuICAgICAgfSxcbiAgICAgIGJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QsXG4gICAgfSk7XG5cbiAgICBjb25zdCBzY2hlZHVsZSA9IG5ldyBSdWxlKHRoaXMsIFwiRXZlbnRSdWxlXCIsIHtcbiAgICAgIHNjaGVkdWxlOiBwcm9wcy5zY2hlZHVsZSB8fCBTY2hlZHVsZS5yYXRlKER1cmF0aW9uLmhvdXJzKDEpKSxcbiAgICAgIC4uLnByb3BzLnJ1bGVQcm9wcyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGxhbWJkYSA9IG5ldyBGdW5jdGlvbih0aGlzLCBcIkhlYWRlckNoZWNrXCIsIHtcbiAgICAgIGFyY2hpdGVjdHVyZTogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gICAgICBoYW5kbGVyOiBcImhlYWRlci1jaGVjay5oYW5kbGVyXCIsXG4gICAgICBjb2RlOiBDb2RlLmZyb21Bc3NldChqb2luKF9fZGlybmFtZSwgXCJsYW1iZGFcIiksIHtcbiAgICAgICAgYnVuZGxpbmc6IHtcbiAgICAgICAgICBjb21tYW5kLFxuICAgICAgICAgIGltYWdlOiBEb2NrZXJJbWFnZS5mcm9tUmVnaXN0cnkoXCJidXN5Ym94XCIpLFxuICAgICAgICAgIGxvY2FsOiBuZXcgRXNidWlsZCh7XG4gICAgICAgICAgICBlbnRyeVBvaW50czogW2pvaW4oX19kaXJuYW1lLCBcImxhbWJkYS9oZWFkZXItY2hlY2sudHNcIildLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBVUkxTOiBwcm9wcy51cmxzLmpvaW4oXCIsXCIpLFxuICAgICAgICBIRUFERVJTOiBoZWFkZXJzLmpvaW4oXCIsXCIpLFxuICAgICAgICBUQUJMRTogdGFibGUudGFibGVOYW1lLFxuICAgICAgICBUT1BJQ19BUk46IHByb3BzLnNuc1RvcGljLnRvcGljLnRvcGljQXJuLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHNjaGVkdWxlLmFkZFRhcmdldChuZXcgTGFtYmRhRnVuY3Rpb24obGFtYmRhKSk7XG5cbiAgICB0YWJsZS5ncmFudFdyaXRlRGF0YShsYW1iZGEpO1xuICAgIHRhYmxlLmdyYW50UmVhZERhdGEobGFtYmRhKTtcbiAgICBwcm9wcy5zbnNUb3BpYy50b3BpYy5ncmFudFB1Ymxpc2gobGFtYmRhKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const handler: () => Promise<void>;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// We know the environment variables will exist so safe to ignore this
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.handler = void 0;
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
11
|
+
const client_sns_1 = require("@aws-sdk/client-sns");
|
|
12
|
+
const URLS = process.env.URLS;
|
|
13
|
+
const HEADERS = process.env.HEADERS;
|
|
14
|
+
const TABLE = process.env.TABLE;
|
|
15
|
+
const config = "";
|
|
16
|
+
const DB_CLIENT = new client_dynamodb_1.DynamoDBClient(config);
|
|
17
|
+
const securityHeaders = (HEADERS === null || HEADERS === void 0 ? void 0 : HEADERS.split(",")) || [];
|
|
18
|
+
const handler = async () => {
|
|
19
|
+
const urls = (URLS === null || URLS === void 0 ? void 0 : URLS.split(",")) || [];
|
|
20
|
+
// Fetch stored headers
|
|
21
|
+
const [storedUrlHeaders, currentUrlHeaders] = await Promise.all([
|
|
22
|
+
getStoredValues(urls),
|
|
23
|
+
fetchHeaders(urls),
|
|
24
|
+
]);
|
|
25
|
+
// Find any differences between the headers
|
|
26
|
+
const headerDifferences = new Map();
|
|
27
|
+
let differencesDetected = false;
|
|
28
|
+
const dbUpdates = urls.map(url => {
|
|
29
|
+
var _a;
|
|
30
|
+
const currentHeaders = currentUrlHeaders.get(url);
|
|
31
|
+
const storedHeaders = storedUrlHeaders.get(url) || new Map();
|
|
32
|
+
if (!currentHeaders)
|
|
33
|
+
throw new Error(`Could not get current headers for ${url}`);
|
|
34
|
+
// Check all headers that we care about
|
|
35
|
+
headerDifferences.set(url, compareHeaders(securityHeaders, storedHeaders, currentHeaders));
|
|
36
|
+
const headersToUpdate = new Map();
|
|
37
|
+
(_a = headerDifferences.get(url)) === null || _a === void 0 ? void 0 : _a.forEach(difference => {
|
|
38
|
+
headersToUpdate.set(difference.header, difference.currentValue);
|
|
39
|
+
differencesDetected = true;
|
|
40
|
+
});
|
|
41
|
+
return updateStoredValues(url, headersToUpdate);
|
|
42
|
+
});
|
|
43
|
+
await Promise.all(dbUpdates);
|
|
44
|
+
if (differencesDetected)
|
|
45
|
+
await sendToSns(formatDifferences(headerDifferences));
|
|
46
|
+
};
|
|
47
|
+
exports.handler = handler;
|
|
48
|
+
/**
|
|
49
|
+
* Fetch security headers for the given urls
|
|
50
|
+
*
|
|
51
|
+
* @param urls list of urls to fetch headers from
|
|
52
|
+
*/
|
|
53
|
+
const fetchHeaders = async (urls) => {
|
|
54
|
+
const currentUrlHeaders = new Map();
|
|
55
|
+
// Make an axios request for each url
|
|
56
|
+
await Promise.all(urls.map(url => axios_1.default.get(url).then(response => {
|
|
57
|
+
// Then get all the security headers from each response
|
|
58
|
+
const headers = new Map();
|
|
59
|
+
Object.entries(response.headers).forEach(([headerName, value]) => {
|
|
60
|
+
if (securityHeaders === null || securityHeaders === void 0 ? void 0 : securityHeaders.includes(headerName))
|
|
61
|
+
headers.set(headerName, value);
|
|
62
|
+
});
|
|
63
|
+
currentUrlHeaders.set(url, headers);
|
|
64
|
+
})));
|
|
65
|
+
return currentUrlHeaders;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Get values stored in DynamoDB table from a list of string keys.
|
|
69
|
+
* Assumes the call is made to the header change detection table.
|
|
70
|
+
* This table has a primary key of Url (string) with an unknown
|
|
71
|
+
* number of string fields.
|
|
72
|
+
*
|
|
73
|
+
* @param keys array of strings
|
|
74
|
+
*/
|
|
75
|
+
const getStoredValues = async (keys) => {
|
|
76
|
+
if (keys.length === 0) {
|
|
77
|
+
console.log("No keys were passed");
|
|
78
|
+
return new Map();
|
|
79
|
+
}
|
|
80
|
+
// Construct the command input
|
|
81
|
+
const primaryKeys = keys.map(url => {
|
|
82
|
+
return {
|
|
83
|
+
Url: {
|
|
84
|
+
S: url,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
const requestItems = {
|
|
89
|
+
[TABLE]: {
|
|
90
|
+
Keys: primaryKeys,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
return dynamoBatchRequest(requestItems);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Update stored headers for the given url.
|
|
97
|
+
* If the header no longer has a value, delete it. Otherwise update it.
|
|
98
|
+
*
|
|
99
|
+
* @param url the url to update - this is the primary key
|
|
100
|
+
* @param headers record of headers to update
|
|
101
|
+
*/
|
|
102
|
+
const updateStoredValues = async (url, headers) => {
|
|
103
|
+
// Convert headers to attribute value update attributes
|
|
104
|
+
const attributes = {};
|
|
105
|
+
headers.forEach((value, headerName) => {
|
|
106
|
+
// If the value exists update it, otherwise remove it
|
|
107
|
+
if (value) {
|
|
108
|
+
attributes[headerName] = {
|
|
109
|
+
Value: {
|
|
110
|
+
S: value,
|
|
111
|
+
},
|
|
112
|
+
Action: "PUT",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
attributes[headerName] = {
|
|
117
|
+
Action: "DELETE",
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
if (Object.values(attributes).length === 0) {
|
|
122
|
+
console.log(`No attribute value changes for ${url}`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
return dynamoUpdateRequest(url, attributes);
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Recursive function to get multiple items from a DynamoDB table
|
|
129
|
+
*
|
|
130
|
+
* @param requestItems
|
|
131
|
+
* @returns Promise<URLHeaders>
|
|
132
|
+
*/
|
|
133
|
+
const dynamoBatchRequest = async (requestItems) => {
|
|
134
|
+
var _a, _b;
|
|
135
|
+
console.log(`Starting batch request with items: ${JSON.stringify(requestItems)}`);
|
|
136
|
+
// Validate that request items has values
|
|
137
|
+
if (((_a = Object.keys(requestItems || {})) === null || _a === void 0 ? void 0 : _a.length) === 0)
|
|
138
|
+
return new Map();
|
|
139
|
+
const batchGetInput = {
|
|
140
|
+
RequestItems: requestItems,
|
|
141
|
+
};
|
|
142
|
+
const batchGetCommand = new client_dynamodb_1.BatchGetItemCommand(batchGetInput);
|
|
143
|
+
// Fetch stored stored headers
|
|
144
|
+
const response = await DB_CLIENT.send(batchGetCommand);
|
|
145
|
+
const responses = (_b = response.Responses) === null || _b === void 0 ? void 0 : _b[TABLE];
|
|
146
|
+
if (!responses)
|
|
147
|
+
return new Map();
|
|
148
|
+
console.log(`Got following data from dynamo table: ${JSON.stringify(responses)}`);
|
|
149
|
+
const storedUrlHeaders = new Map();
|
|
150
|
+
Object.values(responses).forEach(headers => {
|
|
151
|
+
const urlHeaders = new Map();
|
|
152
|
+
let url = "";
|
|
153
|
+
Object.entries(headers).forEach(([headerName, value]) => {
|
|
154
|
+
if (headerName === "Url") {
|
|
155
|
+
url = value.S;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
urlHeaders.set(headerName, value.S);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
storedUrlHeaders.set(url, urlHeaders);
|
|
162
|
+
});
|
|
163
|
+
// Process any remaining keys
|
|
164
|
+
const nextUrlHeaders = await dynamoBatchRequest(response.UnprocessedKeys);
|
|
165
|
+
// Merge data into one object and return
|
|
166
|
+
return new Map([...storedUrlHeaders, ...nextUrlHeaders]);
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Send an update command to DynamoDB
|
|
170
|
+
*
|
|
171
|
+
* @param url the url to update - this is the primary key
|
|
172
|
+
* @param attributes Record<string, AttributeValueUpdate>
|
|
173
|
+
*/
|
|
174
|
+
const dynamoUpdateRequest = async (url, attributes) => {
|
|
175
|
+
console.log(`Updating ${url} in table with: ${JSON.stringify(Object.entries(attributes))}`);
|
|
176
|
+
const updateItemInput = {
|
|
177
|
+
TableName: TABLE,
|
|
178
|
+
Key: {
|
|
179
|
+
Url: {
|
|
180
|
+
S: url,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
AttributeUpdates: attributes,
|
|
184
|
+
};
|
|
185
|
+
const updateItemCommand = new client_dynamodb_1.UpdateItemCommand(updateItemInput);
|
|
186
|
+
return DB_CLIENT.send(updateItemCommand);
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Compare values of two lists of headers. Return any headers that have differences
|
|
190
|
+
* along with their stored and current values.
|
|
191
|
+
*
|
|
192
|
+
* @param headers list of headers we want to compare
|
|
193
|
+
* @param stored list of headers that were last found on the site
|
|
194
|
+
* @param current list of headers currently on the site
|
|
195
|
+
* @returns
|
|
196
|
+
*/
|
|
197
|
+
const compareHeaders = (headers, stored, current) => {
|
|
198
|
+
const differences = [];
|
|
199
|
+
headers.forEach(header => {
|
|
200
|
+
const currentValue = current.get(header);
|
|
201
|
+
const storedValue = stored.get(header);
|
|
202
|
+
if (currentValue !== storedValue) {
|
|
203
|
+
differences.push({
|
|
204
|
+
header,
|
|
205
|
+
storedValue: storedValue,
|
|
206
|
+
currentValue: currentValue,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
return differences;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Format the differences so they can be easily read in an email.
|
|
214
|
+
*
|
|
215
|
+
* Outputs a string that looks like this:
|
|
216
|
+
*
|
|
217
|
+
* Headers differences found:
|
|
218
|
+
* == https://aligent.com.au/ ===
|
|
219
|
+
*
|
|
220
|
+
* Header: example-header-name
|
|
221
|
+
* Stored Value: No stored value
|
|
222
|
+
* Current Value: example-value
|
|
223
|
+
*
|
|
224
|
+
* === https://aligent.com.au/contact ===
|
|
225
|
+
*
|
|
226
|
+
* Header: example-header-name
|
|
227
|
+
* Stored Value: No stored value
|
|
228
|
+
* Current Value: example-value
|
|
229
|
+
*
|
|
230
|
+
* Header: example-header-name-2
|
|
231
|
+
* Stored Value: previous-value
|
|
232
|
+
* Current Value: new-example-value
|
|
233
|
+
*
|
|
234
|
+
* @param differences Map<string, Difference[]> where the key is the URL
|
|
235
|
+
*/
|
|
236
|
+
const formatDifferences = (differences) => {
|
|
237
|
+
const message = Array.from(differences.keys()).reduce((text, url) => {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
console.log(text, url);
|
|
240
|
+
// Skip the url if there are no differences
|
|
241
|
+
if (((_a = differences.get(url)) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
242
|
+
return text;
|
|
243
|
+
}
|
|
244
|
+
// Format headers nicely
|
|
245
|
+
const headers = (_b = differences.get(url)) === null || _b === void 0 ? void 0 : _b.reduce((headerText, header) => {
|
|
246
|
+
return (headerText += `\r\nHeader: ${header.header}\r\nStored Value: ${header.storedValue}\r\nCurrent Value: ${header.currentValue}\r\n`);
|
|
247
|
+
}, "");
|
|
248
|
+
return `${text}\r\n=== ${url} ===\r\n ${headers}`;
|
|
249
|
+
}, "");
|
|
250
|
+
return `Header differences found${message}`;
|
|
251
|
+
};
|
|
252
|
+
const TOPIC_ARN = process.env.TOPIC_ARN;
|
|
253
|
+
const SNS_CLIENT = new client_sns_1.SNSClient();
|
|
254
|
+
/**
|
|
255
|
+
* Send a message to the SNS topic
|
|
256
|
+
*
|
|
257
|
+
* @param message string to send to sns
|
|
258
|
+
*/
|
|
259
|
+
const sendToSns = async (message) => {
|
|
260
|
+
const publishInput = {
|
|
261
|
+
TopicArn: TOPIC_ARN,
|
|
262
|
+
Message: message,
|
|
263
|
+
};
|
|
264
|
+
const publishCommand = new client_sns_1.PublishCommand(publishInput);
|
|
265
|
+
await SNS_CLIENT.send(publishCommand);
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVyLWNoZWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvaGVhZGVyLWNoYW5nZS1kZXRlY3Rpb24vbGliL2xhbWJkYS9oZWFkZXItY2hlY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHNFQUFzRTtBQUN0RSw2REFBNkQ7Ozs7OztBQUU3RCxrREFBMEI7QUFDMUIsOERBU2tDO0FBQ2xDLG9EQUE4RTtBQUU5RSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztBQUM5QixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQztBQUNwQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQU0sQ0FBQztBQUVqQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDbEIsTUFBTSxTQUFTLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBRTdDLE1BQU0sZUFBZSxHQUFHLENBQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSSxFQUFFLENBQUM7QUFPM0MsTUFBTSxPQUFPLEdBQUcsS0FBSyxJQUFJLEVBQUU7SUFDaEMsTUFBTSxJQUFJLEdBQUcsQ0FBQSxJQUFJLGFBQUosSUFBSSx1QkFBSixJQUFJLENBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFJLEVBQUUsQ0FBQztJQUVwQyx1QkFBdUI7SUFDdkIsTUFBTSxDQUFDLGdCQUFnQixFQUFFLGlCQUFpQixDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQzlELGVBQWUsQ0FBQyxJQUFJLENBQUM7UUFDckIsWUFBWSxDQUFDLElBQUksQ0FBQztLQUNuQixDQUFDLENBQUM7SUFFSCwyQ0FBMkM7SUFDM0MsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsRUFBd0IsQ0FBQztJQUMx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QUksZUFBZSxNQUFNLENBQUMsTUFBTSxxQkFBcUIsTUFBTSxDQUFDLFdBQVcsc0JBQXNCLE1BQU0sQ0FBQyxZQUFZLE1BQU0sQ0FBQyxDQUFDO1FBQzVJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVQLE9BQU8sR0FBRyxJQUFJLFdBQVcsR0FBRyxZQUFZLE9BQU8sRUFBRSxDQUFDO0lBQ3BELENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUVQLE9BQU8sMkJBQTJCLE9BQU8sRUFBRSxDQUFDO0FBQzlDLENBQUMsQ0FBQztBQUVGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBVSxDQUFDO0FBQ3pDLE1BQU0sVUFBVSxHQUFHLElBQUksc0JBQVMsRUFBRSxDQUFDO0FBRW5DOzs7O0dBSUc7QUFDSCxNQUFNLFNBQVMsR0FBRyxLQUFLLEVBQUUsT0FBZSxFQUFFLEVBQUU7SUFDMUMsTUFBTSxZQUFZLEdBQWlCO1FBQ2pDLFFBQVEsRUFBRSxTQUFTO1FBQ25CLE9BQU8sRUFBRSxPQUFPO0tBQ2pCLENBQUM7SUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLDJCQUFjLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDeEQsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3hDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFdlIGtub3cgdGhlIGVudmlyb25tZW50IHZhcmlhYmxlcyB3aWxsIGV4aXN0IHNvIHNhZmUgdG8gaWdub3JlIHRoaXNcbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb24gKi9cblxuaW1wb3J0IGF4aW9zIGZyb20gXCJheGlvc1wiO1xuaW1wb3J0IHtcbiAgRHluYW1vREJDbGllbnQsXG4gIEJhdGNoR2V0SXRlbUNvbW1hbmQsXG4gIEJhdGNoR2V0SXRlbUNvbW1hbmRJbnB1dCxcbiAgS2V5c0FuZEF0dHJpYnV0ZXMsXG4gIFVwZGF0ZUl0ZW1Db21tYW5kSW5wdXQsXG4gIFVwZGF0ZUl0ZW1Db21tYW5kLFxuICBBdHRyaWJ1dGVWYWx1ZVVwZGF0ZSxcbiAgVXBkYXRlSXRlbUNvbW1hbmRPdXRwdXQsXG59IGZyb20gXCJAYXdzLXNkay9jbGllbnQtZHluYW1vZGJcIjtcbmltcG9ydCB7IFB1Ymxpc2hDb21tYW5kLCBQdWJsaXNoSW5wdXQsIFNOU0NsaWVudCB9IGZyb20gXCJAYXdzLXNkay9jbGllbnQtc25zXCI7XG5cbmNvbnN0IFVSTFMgPSBwcm9jZXNzLmVudi5VUkxTO1xuY29uc3QgSEVBREVSUyA9IHByb2Nlc3MuZW52LkhFQURFUlM7XG5jb25zdCBUQUJMRSA9IHByb2Nlc3MuZW52LlRBQkxFITtcblxuY29uc3QgY29uZmlnID0gXCJcIjtcbmNvbnN0IERCX0NMSUVOVCA9IG5ldyBEeW5hbW9EQkNsaWVudChjb25maWcpO1xuXG5jb25zdCBzZWN1cml0eUhlYWRlcnMgPSBIRUFERVJTPy5zcGxpdChcIixcIikgfHwgW107XG5cbnR5cGUgSGVhZGVycyA9IE1hcDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD47XG5cbi8vIEEgbWFwIG9mIFVSTHMgYW5kIHRoZWlyIGhlYWRlcnNcbnR5cGUgVVJMSGVhZGVycyA9IE1hcDxzdHJpbmcsIEhlYWRlcnM+O1xuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jICgpID0+IHtcbiAgY29uc3QgdXJscyA9IFVSTFM/LnNwbGl0KFwiLFwiKSB8fCBbXTtcblxuICAvLyBGZXRjaCBzdG9yZWQgaGVhZGVyc1xuICBjb25zdCBbc3RvcmVkVXJsSGVhZGVycywgY3VycmVudFVybEhlYWRlcnNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGdldFN0b3JlZFZhbHVlcyh1cmxzKSxcbiAgICBmZXRjaEhlYWRlcnModXJscyksXG4gIF0pO1xuXG4gIC8vIEZpbmQgYW55IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGhlYWRlcnNcbiAgY29uc3QgaGVhZGVyRGlmZmVyZW5jZXMgPSBuZXcgTWFwPHN0cmluZywgRGlmZmVyZW5jZVtdPigpO1xuICBsZXQgZGlmZmVyZW5jZXNEZXRlY3RlZCA9IGZhbHNlO1xuICBjb25zdCBkYlVwZGF0ZXMgPSB1cmxzLm1hcCh1cmwgPT4ge1xuICAgIGNvbnN0IGN1cnJlbnRIZWFkZXJzID0gY3VycmVudFVybEhlYWRlcnMuZ2V0KHVybCk7XG4gICAgY29uc3Qgc3RvcmVkSGVhZGVycyA9XG4gICAgICBzdG9yZWRVcmxIZWFkZXJzLmdldCh1cmwpIHx8IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+KCk7XG5cbiAgICBpZiAoIWN1cnJlbnRIZWFkZXJzKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZ2V0IGN1cnJlbnQgaGVhZGVycyBmb3IgJHt1cmx9YCk7XG5cbiAgICAvLyBDaGVjayBhbGwgaGVhZGVycyB0aGF0IHdlIGNhcmUgYWJvdXRcbiAgICBoZWFkZXJEaWZmZXJlbmNlcy5zZXQoXG4gICAgICB1cmwsXG4gICAgICBjb21wYXJlSGVhZGVycyhzZWN1cml0eUhlYWRlcnMsIHN0b3JlZEhlYWRlcnMsIGN1cnJlbnRIZWFkZXJzKVxuICAgICk7XG5cbiAgICBjb25zdCBoZWFkZXJzVG9VcGRhdGU6IEhlYWRlcnMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICAgIGhlYWRlckRpZmZlcmVuY2VzLmdldCh1cmwpPy5mb3JFYWNoKGRpZmZlcmVuY2UgPT4ge1xuICAgICAgaGVhZGVyc1RvVXBkYXRlLnNldChkaWZmZXJlbmNlLmhlYWRlciwgZGlmZmVyZW5jZS5jdXJyZW50VmFsdWUpO1xuICAgICAgZGlmZmVyZW5jZXNEZXRlY3RlZCA9IHRydWU7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdXBkYXRlU3RvcmVkVmFsdWVzKHVybCwgaGVhZGVyc1RvVXBkYXRlKTtcbiAgfSk7XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwoZGJVcGRhdGVzKTtcblxuICBpZiAoZGlmZmVyZW5jZXNEZXRlY3RlZClcbiAgICBhd2FpdCBzZW5kVG9TbnMoZm9ybWF0RGlmZmVyZW5jZXMoaGVhZGVyRGlmZmVyZW5jZXMpKTtcbn07XG5cbi8qKlxuICogRmV0Y2ggc2VjdXJpdHkgaGVhZGVycyBmb3IgdGhlIGdpdmVuIHVybHNcbiAqXG4gKiBAcGFyYW0gdXJscyBsaXN0IG9mIHVybHMgdG8gZmV0Y2ggaGVhZGVycyBmcm9tXG4gKi9cbmNvbnN0IGZldGNoSGVhZGVycyA9IGFzeW5jICh1cmxzOiBzdHJpbmdbXSk6IFByb21pc2U8VVJMSGVhZGVycz4gPT4ge1xuICBjb25zdCBjdXJyZW50VXJsSGVhZGVyczogVVJMSGVhZGVycyA9IG5ldyBNYXA8c3RyaW5nLCBIZWFkZXJzPigpO1xuXG4gIC8vIE1ha2UgYW4gYXhpb3MgcmVxdWVzdCBmb3IgZWFjaCB1cmxcbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgdXJscy5tYXAodXJsID0+XG4gICAgICBheGlvcy5nZXQodXJsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgLy8gVGhlbiBnZXQgYWxsIHRoZSBzZWN1cml0eSBoZWFkZXJzIGZyb20gZWFjaCByZXNwb25zZVxuICAgICAgICBjb25zdCBoZWFkZXJzOiBIZWFkZXJzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcblxuICAgICAgICBPYmplY3QuZW50cmllcyhyZXNwb25zZS5oZWFkZXJzKS5mb3JFYWNoKChbaGVhZGVyTmFtZSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgaWYgKHNlY3VyaXR5SGVhZGVycz8uaW5jbHVkZXMoaGVhZGVyTmFtZSkpXG4gICAgICAgICAgICBoZWFkZXJzLnNldChoZWFkZXJOYW1lLCB2YWx1ZSBhcyBzdHJpbmcpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjdXJyZW50VXJsSGVhZGVycy5zZXQodXJsLCBoZWFkZXJzKTtcbiAgICAgIH0pXG4gICAgKVxuICApO1xuXG4gIHJldHVybiBjdXJyZW50VXJsSGVhZGVycztcbn07XG5cbi8qKlxuICogR2V0IHZhbHVlcyBzdG9yZWQgaW4gRHluYW1vREIgdGFibGUgZnJvbSBhIGxpc3Qgb2Ygc3RyaW5nIGtleXMuXG4gKiBBc3N1bWVzIHRoZSBjYWxsIGlzIG1hZGUgdG8gdGhlIGhlYWRlciBjaGFuZ2UgZGV0ZWN0aW9uIHRhYmxlLlxuICogVGhpcyB0YWJsZSBoYXMgYSBwcmltYXJ5IGtleSBvZiBVcmwgKHN0cmluZykgd2l0aCBhbiB1bmtub3duXG4gKiBudW1iZXIgb2Ygc3RyaW5nIGZpZWxkcy5cbiAqXG4gKiBAcGFyYW0ga2V5cyBhcnJheSBvZiBzdHJpbmdzXG4gKi9cbmNvbnN0IGdldFN0b3JlZFZhbHVlcyA9IGFzeW5jIChrZXlzOiBzdHJpbmdbXSk6IFByb21pc2U8VVJMSGVhZGVycz4gPT4ge1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHtcbiAgICBjb25zb2xlLmxvZyhcIk5vIGtleXMgd2VyZSBwYXNzZWRcIik7XG4gICAgcmV0dXJuIG5ldyBNYXA8c3RyaW5nLCBIZWFkZXJzPigpO1xuICB9XG5cbiAgLy8gQ29uc3RydWN0IHRoZSBjb21tYW5kIGlucHV0XG4gIGNvbnN0IHByaW1hcnlLZXlzID0ga2V5cy5tYXAodXJsID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgVXJsOiB7XG4gICAgICAgIFM6IHVybCxcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG4gIGNvbnN0IHJlcXVlc3RJdGVtcyA9IHtcbiAgICBbVEFCTEVdOiB7XG4gICAgICBLZXlzOiBwcmltYXJ5S2V5cyxcbiAgICB9LFxuICB9O1xuXG4gIHJldHVybiBkeW5hbW9CYXRjaFJlcXVlc3QocmVxdWVzdEl0ZW1zKTtcbn07XG5cbi8qKlxuICogVXBkYXRlIHN0b3JlZCBoZWFkZXJzIGZvciB0aGUgZ2l2ZW4gdXJsLlxuICogSWYgdGhlIGhlYWRlciBubyBsb25nZXIgaGFzIGEgdmFsdWUsIGRlbGV0ZSBpdC4gT3RoZXJ3aXNlIHVwZGF0ZSBpdC5cbiAqXG4gKiBAcGFyYW0gdXJsIHRoZSB1cmwgdG8gdXBkYXRlIC0gdGhpcyBpcyB0aGUgcHJpbWFyeSBrZXlcbiAqIEBwYXJhbSBoZWFkZXJzIHJlY29yZCBvZiBoZWFkZXJzIHRvIHVwZGF0ZVxuICovXG5jb25zdCB1cGRhdGVTdG9yZWRWYWx1ZXMgPSBhc3luYyAoXG4gIHVybDogc3RyaW5nLFxuICBoZWFkZXJzOiBIZWFkZXJzXG4pOiBQcm9taXNlPFVwZGF0ZUl0ZW1Db21tYW5kT3V0cHV0IHwgdW5kZWZpbmVkPiA9PiB7XG4gIC8vIENvbnZlcnQgaGVhZGVycyB0byBhdHRyaWJ1dGUgdmFsdWUgdXBkYXRlIGF0dHJpYnV0ZXNcbiAgY29uc3QgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgQXR0cmlidXRlVmFsdWVVcGRhdGU+ID0ge307XG4gIGhlYWRlcnMuZm9yRWFjaCgodmFsdWUsIGhlYWRlck5hbWUpID0+IHtcbiAgICAvLyBJZiB0aGUgdmFsdWUgZXhpc3RzIHVwZGF0ZSBpdCwgb3RoZXJ3aXNlIHJlbW92ZSBpdFxuICAgIGlmICh2YWx1ZSkge1xuICAgICAgYXR0cmlidXRlc1toZWFkZXJOYW1lXSA9IHtcbiAgICAgICAgVmFsdWU6IHtcbiAgICAgICAgICBTOiB2YWx1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgQWN0aW9uOiBcIlBVVFwiLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXR0cmlidXRlc1toZWFkZXJOYW1lXSA9IHtcbiAgICAgICAgQWN0aW9uOiBcIkRFTEVURVwiLFxuICAgICAgfTtcbiAgICB9XG4gIH0pO1xuXG4gIGlmIChPYmplY3QudmFsdWVzKGF0dHJpYnV0ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgIGNvbnNvbGUubG9nKGBObyBhdHRyaWJ1dGUgdmFsdWUgY2hhbmdlcyBmb3IgJHt1cmx9YCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcmV0dXJuIGR5bmFtb1VwZGF0ZVJlcXVlc3QodXJsLCBhdHRyaWJ1dGVzKTtcbn07XG5cbi8qKlxuICogUmVjdXJzaXZlIGZ1bmN0aW9uIHRvIGdldCBtdWx0aXBsZSBpdGVtcyBmcm9tIGEgRHluYW1vREIgdGFibGVcbiAqXG4gKiBAcGFyYW0gcmVxdWVzdEl0ZW1zXG4gKiBAcmV0dXJucyBQcm9taXNlPFVSTEhlYWRlcnM+XG4gKi9cbmNvbnN0IGR5bmFtb0JhdGNoUmVxdWVzdCA9IGFzeW5jIChcbiAgcmVxdWVzdEl0ZW1zOiBSZWNvcmQ8c3RyaW5nLCBLZXlzQW5kQXR0cmlidXRlcz4gfCB1bmRlZmluZWRcbik6IFByb21pc2U8VVJMSGVhZGVycz4gPT4ge1xuICBjb25zb2xlLmxvZyhcbiAgICBgU3RhcnRpbmcgYmF0Y2ggcmVxdWVzdCB3aXRoIGl0ZW1zOiAke0pTT04uc3RyaW5naWZ5KHJlcXVlc3RJdGVtcyl9YFxuICApO1xuXG4gIC8vIFZhbGlkYXRlIHRoYXQgcmVxdWVzdCBpdGVtcyBoYXMgdmFsdWVzXG4gIGlmIChPYmplY3Qua2V5cyhyZXF1ZXN0SXRlbXMgfHwge30pPy5sZW5ndGggPT09IDApXG4gICAgcmV0dXJuIG5ldyBNYXA8c3RyaW5nLCBIZWFkZXJzPigpO1xuXG4gIGNvbnN0IGJhdGNoR2V0SW5wdXQ6IEJhdGNoR2V0SXRlbUNvbW1hbmRJbnB1dCA9IHtcbiAgICBSZXF1ZXN0SXRlbXM6IHJlcXVlc3RJdGVtcyxcbiAgfTtcbiAgY29uc3QgYmF0Y2hHZXRDb21tYW5kID0gbmV3IEJhdGNoR2V0SXRlbUNvbW1hbmQoYmF0Y2hHZXRJbnB1dCk7XG5cbiAgLy8gRmV0Y2ggc3RvcmVkIHN0b3JlZCBoZWFkZXJzXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgREJfQ0xJRU5ULnNlbmQoYmF0Y2hHZXRDb21tYW5kKTtcbiAgY29uc3QgcmVzcG9uc2VzID0gcmVzcG9uc2UuUmVzcG9uc2VzPy5bVEFCTEVdO1xuXG4gIGlmICghcmVzcG9uc2VzKSByZXR1cm4gbmV3IE1hcDxzdHJpbmcsIEhlYWRlcnM+KCk7XG5cbiAgY29uc29sZS5sb2coXG4gICAgYEdvdCBmb2xsb3dpbmcgZGF0YSBmcm9tIGR5bmFtbyB0YWJsZTogJHtKU09OLnN0cmluZ2lmeShyZXNwb25zZXMpfWBcbiAgKTtcblxuICBjb25zdCBzdG9yZWRVcmxIZWFkZXJzOiBVUkxIZWFkZXJzID0gbmV3IE1hcDxzdHJpbmcsIEhlYWRlcnM+KCk7XG4gIE9iamVjdC52YWx1ZXMocmVzcG9uc2VzKS5mb3JFYWNoKGhlYWRlcnMgPT4ge1xuICAgIGNvbnN0IHVybEhlYWRlcnM6IEhlYWRlcnMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuXG4gICAgbGV0IHVybCA9IFwiXCI7XG4gICAgT2JqZWN0LmVudHJpZXMoaGVhZGVycykuZm9yRWFjaCgoW2hlYWRlck5hbWUsIHZhbHVlXSkgPT4ge1xuICAgICAgaWYgKGhlYWRlck5hbWUgPT09IFwiVXJsXCIpIHtcbiAgICAgICAgdXJsID0gdmFsdWUuUyE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1cmxIZWFkZXJzLnNldChoZWFkZXJOYW1lLCB2YWx1ZS5TISk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgc3RvcmVkVXJsSGVhZGVycy5zZXQodXJsLCB1cmxIZWFkZXJzKTtcbiAgfSk7XG5cbiAgLy8gUHJvY2VzcyBhbnkgcmVtYWluaW5nIGtleXNcbiAgY29uc3QgbmV4dFVybEhlYWRlcnMgPSBhd2FpdCBkeW5hbW9CYXRjaFJlcXVlc3QocmVzcG9uc2UuVW5wcm9jZXNzZWRLZXlzKTtcblxuICAvLyBNZXJnZSBkYXRhIGludG8gb25lIG9iamVjdCBhbmQgcmV0dXJuXG4gIHJldHVybiBuZXcgTWFwPHN0cmluZywgSGVhZGVycz4oWy4uLnN0b3JlZFVybEhlYWRlcnMsIC4uLm5leHRVcmxIZWFkZXJzXSk7XG59O1xuXG4vKipcbiAqIFNlbmQgYW4gdXBkYXRlIGNvbW1hbmQgdG8gRHluYW1vREJcbiAqXG4gKiBAcGFyYW0gdXJsIHRoZSB1cmwgdG8gdXBkYXRlIC0gdGhpcyBpcyB0aGUgcHJpbWFyeSBrZXlcbiAqIEBwYXJhbSBhdHRyaWJ1dGVzIFJlY29yZDxzdHJpbmcsIEF0dHJpYnV0ZVZhbHVlVXBkYXRlPlxuICovXG5jb25zdCBkeW5hbW9VcGRhdGVSZXF1ZXN0ID0gYXN5bmMgKFxuICB1cmw6IHN0cmluZyxcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgQXR0cmlidXRlVmFsdWVVcGRhdGU+XG4pOiBQcm9taXNlPFVwZGF0ZUl0ZW1Db21tYW5kT3V0cHV0PiA9PiB7XG4gIGNvbnNvbGUubG9nKFxuICAgIGBVcGRhdGluZyAke3VybH0gaW4gdGFibGUgd2l0aDogJHtKU09OLnN0cmluZ2lmeShPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSl9YFxuICApO1xuXG4gIGNvbnN0IHVwZGF0ZUl0ZW1JbnB1dDogVXBkYXRlSXRlbUNvbW1hbmRJbnB1dCA9IHtcbiAgICBUYWJsZU5hbWU6IFRBQkxFLFxuICAgIEtleToge1xuICAgICAgVXJsOiB7XG4gICAgICAgIFM6IHVybCxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBBdHRyaWJ1dGVVcGRhdGVzOiBhdHRyaWJ1dGVzLFxuICB9O1xuICBjb25zdCB1cGRhdGVJdGVtQ29tbWFuZCA9IG5ldyBVcGRhdGVJdGVtQ29tbWFuZCh1cGRhdGVJdGVtSW5wdXQpO1xuXG4gIHJldHVybiBEQl9DTElFTlQuc2VuZCh1cGRhdGVJdGVtQ29tbWFuZCk7XG59O1xuXG5pbnRlcmZhY2UgRGlmZmVyZW5jZSB7XG4gIGhlYWRlcjogc3RyaW5nO1xuICBzdG9yZWRWYWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBjdXJyZW50VmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBDb21wYXJlIHZhbHVlcyBvZiB0d28gbGlzdHMgb2YgaGVhZGVycy4gUmV0dXJuIGFueSBoZWFkZXJzIHRoYXQgaGF2ZSBkaWZmZXJlbmNlc1xuICogYWxvbmcgd2l0aCB0aGVpciBzdG9yZWQgYW5kIGN1cnJlbnQgdmFsdWVzLlxuICpcbiAqIEBwYXJhbSBoZWFkZXJzIGxpc3Qgb2YgaGVhZGVycyB3ZSB3YW50IHRvIGNvbXBhcmVcbiAqIEBwYXJhbSBzdG9yZWQgbGlzdCBvZiBoZWFkZXJzIHRoYXQgd2VyZSBsYXN0IGZvdW5kIG9uIHRoZSBzaXRlXG4gKiBAcGFyYW0gY3VycmVudCBsaXN0IG9mIGhlYWRlcnMgY3VycmVudGx5IG9uIHRoZSBzaXRlXG4gKiBAcmV0dXJuc1xuICovXG5jb25zdCBjb21wYXJlSGVhZGVycyA9IChcbiAgaGVhZGVyczogc3RyaW5nW10sXG4gIHN0b3JlZDogSGVhZGVycyxcbiAgY3VycmVudDogSGVhZGVyc1xuKTogRGlmZmVyZW5jZVtdID0+IHtcbiAgY29uc3QgZGlmZmVyZW5jZXM6IERpZmZlcmVuY2VbXSA9IFtdO1xuXG4gIGhlYWRlcnMuZm9yRWFjaChoZWFkZXIgPT4ge1xuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGN1cnJlbnQuZ2V0KGhlYWRlcik7XG4gICAgY29uc3Qgc3RvcmVkVmFsdWUgPSBzdG9yZWQuZ2V0KGhlYWRlcik7XG5cbiAgICBpZiAoY3VycmVudFZhbHVlICE9PSBzdG9yZWRWYWx1ZSkge1xuICAgICAgZGlmZmVyZW5jZXMucHVzaCh7XG4gICAgICAgIGhlYWRlcixcbiAgICAgICAgc3RvcmVkVmFsdWU6IHN0b3JlZFZhbHVlLFxuICAgICAgICBjdXJyZW50VmFsdWU6IGN1cnJlbnRWYWx1ZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGRpZmZlcmVuY2VzO1xufTtcblxuLyoqXG4gKiBGb3JtYXQgdGhlIGRpZmZlcmVuY2VzIHNvIHRoZXkgY2FuIGJlIGVhc2lseSByZWFkIGluIGFuIGVtYWlsLlxuICpcbiAqIE91dHB1dHMgYSBzdHJpbmcgdGhhdCBsb29rcyBsaWtlIHRoaXM6XG4gKlxuICogSGVhZGVycyBkaWZmZXJlbmNlcyBmb3VuZDpcbiAqID09IGh0dHBzOi8vYWxpZ2VudC5jb20uYXUvID09PVxuICpcbiAqIEhlYWRlcjogZXhhbXBsZS1oZWFkZXItbmFtZVxuICogU3RvcmVkIFZhbHVlOiBObyBzdG9yZWQgdmFsdWVcbiAqIEN1cnJlbnQgVmFsdWU6IGV4YW1wbGUtdmFsdWVcbiAqXG4gKiA9PT0gaHR0cHM6Ly9hbGlnZW50LmNvbS5hdS9jb250YWN0ID09PVxuICpcbiAqIEhlYWRlcjogZXhhbXBsZS1oZWFkZXItbmFtZVxuICogU3RvcmVkIFZhbHVlOiBObyBzdG9yZWQgdmFsdWVcbiAqIEN1cnJlbnQgVmFsdWU6IGV4YW1wbGUtdmFsdWVcbiAqXG4gKiBIZWFkZXI6IGV4YW1wbGUtaGVhZGVyLW5hbWUtMlxuICogU3RvcmVkIFZhbHVlOiBwcmV2aW91cy12YWx1ZVxuICogQ3VycmVudCBWYWx1ZTogbmV3LWV4YW1wbGUtdmFsdWVcbiAqXG4gKiBAcGFyYW0gZGlmZmVyZW5jZXMgTWFwPHN0cmluZywgRGlmZmVyZW5jZVtdPiB3aGVyZSB0aGUga2V5IGlzIHRoZSBVUkxcbiAqL1xuY29uc3QgZm9ybWF0RGlmZmVyZW5jZXMgPSAoZGlmZmVyZW5jZXM6IE1hcDxzdHJpbmcsIERpZmZlcmVuY2VbXT4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBtZXNzYWdlID0gQXJyYXkuZnJvbShkaWZmZXJlbmNlcy5rZXlzKCkpLnJlZHVjZSgodGV4dCwgdXJsKSA9PiB7XG4gICAgY29uc29sZS5sb2codGV4dCwgdXJsKTtcbiAgICAvLyBTa2lwIHRoZSB1cmwgaWYgdGhlcmUgYXJlIG5vIGRpZmZlcmVuY2VzXG4gICAgaWYgKGRpZmZlcmVuY2VzLmdldCh1cmwpPy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIC8vIEZvcm1hdCBoZWFkZXJzIG5pY2VseVxuICAgIGNvbnN0IGhlYWRlcnMgPSBkaWZmZXJlbmNlcy5nZXQodXJsKT8ucmVkdWNlKChoZWFkZXJUZXh0LCBoZWFkZXIpID0+IHtcbiAgICAgIHJldHVybiAoaGVhZGVyVGV4dCArPSBgXFxyXFxuSGVhZGVyOiAke2hlYWRlci5oZWFkZXJ9XFxyXFxuU3RvcmVkIFZhbHVlOiAke2hlYWRlci5zdG9yZWRWYWx1ZX1cXHJcXG5DdXJyZW50IFZhbHVlOiAke2hlYWRlci5jdXJyZW50VmFsdWV9XFxyXFxuYCk7XG4gICAgfSwgXCJcIik7XG5cbiAgICByZXR1cm4gYCR7dGV4dH1cXHJcXG49PT0gJHt1cmx9ID09PVxcclxcbiAke2hlYWRlcnN9YDtcbiAgfSwgXCJcIik7XG5cbiAgcmV0dXJuIGBIZWFkZXIgZGlmZmVyZW5jZXMgZm91bmQke21lc3NhZ2V9YDtcbn07XG5cbmNvbnN0IFRPUElDX0FSTiA9IHByb2Nlc3MuZW52LlRPUElDX0FSTiE7XG5jb25zdCBTTlNfQ0xJRU5UID0gbmV3IFNOU0NsaWVudCgpO1xuXG4vKipcbiAqIFNlbmQgYSBtZXNzYWdlIHRvIHRoZSBTTlMgdG9waWNcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBzdHJpbmcgdG8gc2VuZCB0byBzbnNcbiAqL1xuY29uc3Qgc2VuZFRvU25zID0gYXN5bmMgKG1lc3NhZ2U6IHN0cmluZykgPT4ge1xuICBjb25zdCBwdWJsaXNoSW5wdXQ6IFB1Ymxpc2hJbnB1dCA9IHtcbiAgICBUb3BpY0FybjogVE9QSUNfQVJOLFxuICAgIE1lc3NhZ2U6IG1lc3NhZ2UsXG4gIH07XG4gIGNvbnN0IHB1Ymxpc2hDb21tYW5kID0gbmV3IFB1Ymxpc2hDb21tYW5kKHB1Ymxpc2hJbnB1dCk7XG4gIGF3YWl0IFNOU19DTElFTlQuc2VuZChwdWJsaXNoQ29tbWFuZCk7XG59O1xuIl19
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aligent/cdk-header-change-detection",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"license": "GPL-3.0-only",
|
|
6
|
+
"homepage": "https://github.com/aligent/cdk-constructs/packages/header-change-detection-stack#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/aligent/aws-cdk-header-change-detection-stack"
|
|
10
|
+
},
|
|
11
|
+
"types": "index.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/jest": "^29.5.10",
|
|
17
|
+
"@types/node": "20.6.3",
|
|
18
|
+
"aws-cdk": "2.113.0",
|
|
19
|
+
"jest": "^29.7.0",
|
|
20
|
+
"ts-jest": "^29.1.1",
|
|
21
|
+
"ts-node": "^10.9.1",
|
|
22
|
+
"typescript": "~5.3.2"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@aws-sdk/client-dynamodb": "^3.726.1",
|
|
26
|
+
"@aws-sdk/client-sns": "3.732.0",
|
|
27
|
+
"aws-cdk-lib": "2.113.0",
|
|
28
|
+
"axios": "^1.7.9",
|
|
29
|
+
"constructs": "^10.3.0",
|
|
30
|
+
"source-map-support": "^0.5.21"
|
|
31
|
+
},
|
|
32
|
+
"type": "commonjs"
|
|
33
|
+
}
|