@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 ADDED
@@ -0,0 +1,2 @@
1
+ import { HeaderChangeDetection, HeaderChangeDetectionProps } from "./lib/header-change-detection";
2
+ export { HeaderChangeDetection, HeaderChangeDetectionProps };
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
+ }