@beesolve/cdk-constructs 0.1.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/README.md +9 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +247 -0
- package/package.json +42 -0
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { DistributionProps } from "aws-cdk-lib/aws-cloudfront";
|
|
2
|
+
import { Construct } from "constructs";
|
|
3
|
+
/**
|
|
4
|
+
* List of all CloudFront access log columns.
|
|
5
|
+
*
|
|
6
|
+
* @link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat
|
|
7
|
+
*/
|
|
8
|
+
declare const cloudFrontAccessLogColumns: readonly [{
|
|
9
|
+
readonly name: "date";
|
|
10
|
+
readonly type: "date";
|
|
11
|
+
}, {
|
|
12
|
+
readonly name: "time";
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
}, {
|
|
15
|
+
readonly name: "x-edge-location";
|
|
16
|
+
readonly type: "string";
|
|
17
|
+
}, {
|
|
18
|
+
readonly name: "sc-bytes";
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
}, {
|
|
21
|
+
readonly name: "c-ip";
|
|
22
|
+
readonly type: "string";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "cs-method";
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
}, {
|
|
27
|
+
readonly name: "cs(Host)";
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
}, {
|
|
30
|
+
readonly name: "cs-uri-stem";
|
|
31
|
+
readonly type: "string";
|
|
32
|
+
}, {
|
|
33
|
+
readonly name: "sc-status";
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
}, {
|
|
36
|
+
readonly name: "cs(Referer)";
|
|
37
|
+
readonly type: "string";
|
|
38
|
+
}, {
|
|
39
|
+
readonly name: "cs(User-Agent)";
|
|
40
|
+
readonly type: "string";
|
|
41
|
+
}, {
|
|
42
|
+
readonly name: "cs-uri-query";
|
|
43
|
+
readonly type: "string";
|
|
44
|
+
}, {
|
|
45
|
+
readonly name: "cs(Cookie)";
|
|
46
|
+
readonly type: "string";
|
|
47
|
+
}, {
|
|
48
|
+
readonly name: "x-edge-result-type";
|
|
49
|
+
readonly type: "string";
|
|
50
|
+
}, {
|
|
51
|
+
readonly name: "x-edge-request-id";
|
|
52
|
+
readonly type: "string";
|
|
53
|
+
}, {
|
|
54
|
+
readonly name: "x-host-header";
|
|
55
|
+
readonly type: "string";
|
|
56
|
+
}, {
|
|
57
|
+
readonly name: "cs-protocol";
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
}, {
|
|
60
|
+
readonly name: "cs-bytes";
|
|
61
|
+
readonly type: "string";
|
|
62
|
+
}, {
|
|
63
|
+
readonly name: "time-taken";
|
|
64
|
+
readonly type: "string";
|
|
65
|
+
}, {
|
|
66
|
+
readonly name: "x-forwarded-for";
|
|
67
|
+
readonly type: "string";
|
|
68
|
+
}, {
|
|
69
|
+
readonly name: "ssl-protocol";
|
|
70
|
+
readonly type: "string";
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "ssl-cipher";
|
|
73
|
+
readonly type: "string";
|
|
74
|
+
}, {
|
|
75
|
+
readonly name: "x-edge-response-result-type";
|
|
76
|
+
readonly type: "string";
|
|
77
|
+
}, {
|
|
78
|
+
readonly name: "cs-protocol-version";
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
}, {
|
|
81
|
+
readonly name: "fle-status";
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
}, {
|
|
84
|
+
readonly name: "fle-encrypted-fields";
|
|
85
|
+
readonly type: "string";
|
|
86
|
+
}, {
|
|
87
|
+
readonly name: "c-port";
|
|
88
|
+
readonly type: "string";
|
|
89
|
+
}, {
|
|
90
|
+
readonly name: "time-to-first-byte";
|
|
91
|
+
readonly type: "string";
|
|
92
|
+
}, {
|
|
93
|
+
readonly name: "x-edge-detailed-result-type";
|
|
94
|
+
readonly type: "string";
|
|
95
|
+
}, {
|
|
96
|
+
readonly name: "sc-content-type";
|
|
97
|
+
readonly type: "string";
|
|
98
|
+
}, {
|
|
99
|
+
readonly name: "sc-content-len";
|
|
100
|
+
readonly type: "string";
|
|
101
|
+
}, {
|
|
102
|
+
readonly name: "sc-range-start";
|
|
103
|
+
readonly type: "string";
|
|
104
|
+
}, {
|
|
105
|
+
readonly name: "sc-range-end";
|
|
106
|
+
readonly type: "string";
|
|
107
|
+
}];
|
|
108
|
+
type CloudFrontAccessLogColumn = (typeof cloudFrontAccessLogColumns)[number]["name"];
|
|
109
|
+
interface CloudFrontAccessLoggingSettingsProps extends Pick<DistributionProps, "logFilePrefix" | "logIncludesCookies"> {
|
|
110
|
+
/**
|
|
111
|
+
* Athena related settings.
|
|
112
|
+
*
|
|
113
|
+
* When not defined, no glue nor athena are being deployed.
|
|
114
|
+
*
|
|
115
|
+
* @default undefined
|
|
116
|
+
*/
|
|
117
|
+
readonly athena?: {
|
|
118
|
+
/**
|
|
119
|
+
* Current account number.
|
|
120
|
+
*/
|
|
121
|
+
readonly account: string;
|
|
122
|
+
/**
|
|
123
|
+
* Provide custom glue database name.
|
|
124
|
+
*
|
|
125
|
+
* @default cf_logs_db
|
|
126
|
+
*/
|
|
127
|
+
readonly glueDbName?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Provide custom glue table name.
|
|
130
|
+
*
|
|
131
|
+
* @default cf_logs_table
|
|
132
|
+
*/
|
|
133
|
+
readonly glueTableName?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Provide custom athena workgroup name.
|
|
136
|
+
*
|
|
137
|
+
* @default cf_workgroup
|
|
138
|
+
*/
|
|
139
|
+
readonly workGroupName?: string;
|
|
140
|
+
/**
|
|
141
|
+
* You can pick individual columns from the access logs which will be stored inside the glue table.
|
|
142
|
+
*
|
|
143
|
+
* @default all available columns
|
|
144
|
+
*/
|
|
145
|
+
readonly columns?: CloudFrontAccessLogColumn[];
|
|
146
|
+
/**
|
|
147
|
+
* When `true` sample query is created within the Athena.
|
|
148
|
+
*
|
|
149
|
+
* @default true
|
|
150
|
+
*/
|
|
151
|
+
readonly createSampleQuery?: boolean;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
declare class CloudFrontAccessLoggingSettings extends Construct {
|
|
155
|
+
readonly cloudFrontLoggingSettings: Pick<DistributionProps, "logBucket" | "logFilePrefix" | "enableLogging" | "logIncludesCookies">;
|
|
156
|
+
constructor(scope: Construct, id: string, props: CloudFrontAccessLoggingSettingsProps);
|
|
157
|
+
}
|
|
158
|
+
import { Duration } from "aws-cdk-lib";
|
|
159
|
+
import { Function } from "aws-cdk-lib/aws-lambda";
|
|
160
|
+
import { Queue } from "aws-cdk-lib/aws-sqs";
|
|
161
|
+
import { Construct as Construct2 } from "constructs";
|
|
162
|
+
declare class EmailAlarms extends Construct2 {
|
|
163
|
+
private emailSubscription;
|
|
164
|
+
constructor(scope: Construct2, id: string, props: {
|
|
165
|
+
readonly emailAddress: string;
|
|
166
|
+
});
|
|
167
|
+
readonly reportLambdaErrors: (handler: Function) => void;
|
|
168
|
+
readonly reportSqsErrors: (props: {
|
|
169
|
+
readonly queue: Queue;
|
|
170
|
+
readonly dlq: Queue;
|
|
171
|
+
readonly noMessagesPeriod?: Duration;
|
|
172
|
+
readonly noConsumersPeriod?: Duration;
|
|
173
|
+
}) => void;
|
|
174
|
+
}
|
|
175
|
+
import { Function as Function2 } from "aws-cdk-lib/aws-lambda";
|
|
176
|
+
import { SqsEventSourceProps } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
177
|
+
import { Queue as Queue2, QueueProps } from "aws-cdk-lib/aws-sqs";
|
|
178
|
+
import { Construct as Construct3 } from "constructs";
|
|
179
|
+
interface SqsWithDlqProps {
|
|
180
|
+
readonly queue?: QueueProps;
|
|
181
|
+
readonly dlq?: Partial<Omit<QueueProps, "fifo" | "contentBasedDeduplication" | "deduplicationScope">>;
|
|
182
|
+
}
|
|
183
|
+
declare class SqsWithDlq extends Construct3 {
|
|
184
|
+
readonly queue: Queue2;
|
|
185
|
+
readonly dlq: Queue2;
|
|
186
|
+
constructor(scope: Construct3, id: string, props?: SqsWithDlqProps);
|
|
187
|
+
/**
|
|
188
|
+
* Uses the queue as an input for the given lambda function.
|
|
189
|
+
*
|
|
190
|
+
* Allows to batch and throttle the lambda invocations.
|
|
191
|
+
*/
|
|
192
|
+
static asLambdaInput(props: SqsWithDlqLambdaInputProps): SqsWithDlq;
|
|
193
|
+
}
|
|
194
|
+
interface SqsWithDlqLambdaInputProps extends SqsWithDlqProps {
|
|
195
|
+
/**
|
|
196
|
+
* Lambda function used to handle the SQS messages.
|
|
197
|
+
*/
|
|
198
|
+
readonly lambda: Function2;
|
|
199
|
+
/**
|
|
200
|
+
* SQS message batching configuration.
|
|
201
|
+
*/
|
|
202
|
+
readonly batching?: BatchingConfig;
|
|
203
|
+
/**
|
|
204
|
+
* Set to true to disable the consumption of messages.
|
|
205
|
+
*
|
|
206
|
+
* Useful when the processing needs to be paused during maintenance.
|
|
207
|
+
*
|
|
208
|
+
* @default false
|
|
209
|
+
*/
|
|
210
|
+
readonly disabled?: boolean;
|
|
211
|
+
}
|
|
212
|
+
type BatchingConfig = Pick<SqsEventSourceProps, "batchSize" | "maxBatchingWindow" | "reportBatchItemFailures" | "maxConcurrency">;
|
|
213
|
+
export { SqsWithDlqProps, SqsWithDlqLambdaInputProps, SqsWithDlq, EmailAlarms, CloudFrontAccessLoggingSettingsProps, CloudFrontAccessLoggingSettings };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// packages/cdk-constructs/src/cloudFrontAccessLoggingSettings.ts
|
|
2
|
+
import { isNotNil } from "@beesolve/helpers";
|
|
3
|
+
import { CfnNamedQuery, CfnWorkGroup } from "aws-cdk-lib/aws-athena";
|
|
4
|
+
import { CfnDatabase, CfnTable } from "aws-cdk-lib/aws-glue";
|
|
5
|
+
import { Bucket, ObjectOwnership } from "aws-cdk-lib/aws-s3";
|
|
6
|
+
import { Construct } from "constructs";
|
|
7
|
+
var cloudFrontAccessLogColumns = [
|
|
8
|
+
{ name: "date", type: "date" },
|
|
9
|
+
{ name: "time", type: "string" },
|
|
10
|
+
{ name: "x-edge-location", type: "string" },
|
|
11
|
+
{ name: "sc-bytes", type: "string" },
|
|
12
|
+
{ name: "c-ip", type: "string" },
|
|
13
|
+
{ name: "cs-method", type: "string" },
|
|
14
|
+
{ name: "cs(Host)", type: "string" },
|
|
15
|
+
{ name: "cs-uri-stem", type: "string" },
|
|
16
|
+
{ name: "sc-status", type: "string" },
|
|
17
|
+
{ name: "cs(Referer)", type: "string" },
|
|
18
|
+
{ name: "cs(User-Agent)", type: "string" },
|
|
19
|
+
{ name: "cs-uri-query", type: "string" },
|
|
20
|
+
{ name: "cs(Cookie)", type: "string" },
|
|
21
|
+
{ name: "x-edge-result-type", type: "string" },
|
|
22
|
+
{ name: "x-edge-request-id", type: "string" },
|
|
23
|
+
{ name: "x-host-header", type: "string" },
|
|
24
|
+
{ name: "cs-protocol", type: "string" },
|
|
25
|
+
{ name: "cs-bytes", type: "string" },
|
|
26
|
+
{ name: "time-taken", type: "string" },
|
|
27
|
+
{ name: "x-forwarded-for", type: "string" },
|
|
28
|
+
{ name: "ssl-protocol", type: "string" },
|
|
29
|
+
{ name: "ssl-cipher", type: "string" },
|
|
30
|
+
{ name: "x-edge-response-result-type", type: "string" },
|
|
31
|
+
{ name: "cs-protocol-version", type: "string" },
|
|
32
|
+
{ name: "fle-status", type: "string" },
|
|
33
|
+
{ name: "fle-encrypted-fields", type: "string" },
|
|
34
|
+
{ name: "c-port", type: "string" },
|
|
35
|
+
{ name: "time-to-first-byte", type: "string" },
|
|
36
|
+
{ name: "x-edge-detailed-result-type", type: "string" },
|
|
37
|
+
{ name: "sc-content-type", type: "string" },
|
|
38
|
+
{ name: "sc-content-len", type: "string" },
|
|
39
|
+
{ name: "sc-range-start", type: "string" },
|
|
40
|
+
{ name: "sc-range-end", type: "string" }
|
|
41
|
+
];
|
|
42
|
+
var columnDefinitionByKey = Object.fromEntries(cloudFrontAccessLogColumns.map((value) => [value.name, value]));
|
|
43
|
+
|
|
44
|
+
class CloudFrontAccessLoggingSettings extends Construct {
|
|
45
|
+
cloudFrontLoggingSettings;
|
|
46
|
+
constructor(scope, id, props) {
|
|
47
|
+
super(scope, id);
|
|
48
|
+
const logBucket = new Bucket(this, "AccessLogs", {
|
|
49
|
+
objectOwnership: ObjectOwnership.OBJECT_WRITER
|
|
50
|
+
});
|
|
51
|
+
if (props.athena != null) {
|
|
52
|
+
const databaseName = props.athena.glueDbName ?? "cf_logs_db";
|
|
53
|
+
const tableName = props.athena.glueTableName ?? "cf_logs_table";
|
|
54
|
+
const workgroupName = props.athena.workGroupName ?? "cf_workgroup";
|
|
55
|
+
const glueDatabase = new CfnDatabase(this, "AccessLogsGlueDb", {
|
|
56
|
+
catalogId: props.athena.account,
|
|
57
|
+
databaseInput: {
|
|
58
|
+
description: "Glue DB for CloudFront access logs",
|
|
59
|
+
name: databaseName
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const glueTable = new CfnTable(this, "AccessLogsGlueTable", {
|
|
63
|
+
catalogId: props.athena.account,
|
|
64
|
+
databaseName,
|
|
65
|
+
tableInput: {
|
|
66
|
+
name: tableName,
|
|
67
|
+
description: "Glue table for CloudFront access logs",
|
|
68
|
+
storageDescriptor: {
|
|
69
|
+
columns: props.athena.columns == null ? [...cloudFrontAccessLogColumns] : Array.from(new Set(props.athena.columns)).map((column) => columnDefinitionByKey[column]).filter(isNotNil),
|
|
70
|
+
location: `s3://${logBucket.bucketName}/${props.logFilePrefix ?? ""}`,
|
|
71
|
+
inputFormat: "org.apache.hadoop.mapred.TextInputFormat",
|
|
72
|
+
outputFormat: "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
|
|
73
|
+
serdeInfo: {
|
|
74
|
+
serializationLibrary: "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe",
|
|
75
|
+
parameters: {
|
|
76
|
+
"serialization.format": "\t",
|
|
77
|
+
"field.delim": "\t"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
parameters: {
|
|
82
|
+
"skip.header.line.count": 2
|
|
83
|
+
},
|
|
84
|
+
tableType: "EXTERNAL_TABLE"
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
glueTable.addDependency(glueDatabase);
|
|
88
|
+
const athenaBucket = new Bucket(this, "AthenaBucket");
|
|
89
|
+
const workgroup = new CfnWorkGroup(this, "Workgroup", {
|
|
90
|
+
name: workgroupName,
|
|
91
|
+
workGroupConfiguration: {
|
|
92
|
+
resultConfiguration: {
|
|
93
|
+
outputLocation: `s3://${athenaBucket.bucketName}/`
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (props.athena.createSampleQuery !== false) {
|
|
98
|
+
const sampleQuery = new CfnNamedQuery(this, "SampleNamedQuery", {
|
|
99
|
+
name: "sample_query",
|
|
100
|
+
queryString: `SELECT * FROM "${databaseName}"."${tableName}" limit 25;`,
|
|
101
|
+
database: databaseName,
|
|
102
|
+
workGroup: workgroup.name
|
|
103
|
+
});
|
|
104
|
+
sampleQuery.addDependency(workgroup);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.cloudFrontLoggingSettings = {
|
|
108
|
+
enableLogging: true,
|
|
109
|
+
logBucket,
|
|
110
|
+
logFilePrefix: props.logFilePrefix,
|
|
111
|
+
logIncludesCookies: props.logIncludesCookies ?? false
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// packages/cdk-constructs/src/emailAlarms.ts
|
|
116
|
+
import {
|
|
117
|
+
Alarm,
|
|
118
|
+
ComparisonOperator,
|
|
119
|
+
TreatMissingData
|
|
120
|
+
} from "aws-cdk-lib/aws-cloudwatch";
|
|
121
|
+
import { SnsAction } from "aws-cdk-lib/aws-cloudwatch-actions";
|
|
122
|
+
import { Topic } from "aws-cdk-lib/aws-sns";
|
|
123
|
+
import { EmailSubscription } from "aws-cdk-lib/aws-sns-subscriptions";
|
|
124
|
+
import { Construct as Construct2 } from "constructs";
|
|
125
|
+
|
|
126
|
+
class EmailAlarms extends Construct2 {
|
|
127
|
+
emailSubscription;
|
|
128
|
+
constructor(scope, id, props) {
|
|
129
|
+
super(scope, id);
|
|
130
|
+
this.emailSubscription = new EmailSubscription(props.emailAddress);
|
|
131
|
+
}
|
|
132
|
+
reportLambdaErrors = (handler) => {
|
|
133
|
+
const topic = new Topic(handler, "ErrorAlarmTopic");
|
|
134
|
+
topic.addSubscription(this.emailSubscription);
|
|
135
|
+
const alarm = new Alarm(handler, `ErrorAlarm`, {
|
|
136
|
+
metric: handler.metricErrors(),
|
|
137
|
+
threshold: 1,
|
|
138
|
+
evaluationPeriods: 1,
|
|
139
|
+
comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
140
|
+
treatMissingData: TreatMissingData.IGNORE
|
|
141
|
+
});
|
|
142
|
+
alarm.addOkAction(new SnsAction(topic));
|
|
143
|
+
alarm.addAlarmAction(new SnsAction(topic));
|
|
144
|
+
};
|
|
145
|
+
reportSqsErrors = (props) => {
|
|
146
|
+
const dlqTopic = new Topic(props.dlq, "DlqAlarmTopic");
|
|
147
|
+
dlqTopic.addSubscription(this.emailSubscription);
|
|
148
|
+
const dlqAlarm = new Alarm(this, "DlqAlarm", {
|
|
149
|
+
alarmDescription: `DLQ for ${props.queue.queueName} is not empty.`,
|
|
150
|
+
metric: props.dlq.metricApproximateNumberOfMessagesVisible(),
|
|
151
|
+
threshold: 1,
|
|
152
|
+
evaluationPeriods: 1,
|
|
153
|
+
comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
154
|
+
treatMissingData: TreatMissingData.IGNORE
|
|
155
|
+
});
|
|
156
|
+
dlqAlarm.addAlarmAction(new SnsAction(dlqTopic));
|
|
157
|
+
if (props.noMessagesPeriod || props.noConsumersPeriod) {
|
|
158
|
+
const queueTopic = new Topic(props.queue, "QueueAlarmTopic");
|
|
159
|
+
queueTopic.addSubscription(this.emailSubscription);
|
|
160
|
+
if (props.noMessagesPeriod) {
|
|
161
|
+
const noMessages = new Alarm(this, "NoMessagesAlarm", {
|
|
162
|
+
alarmDescription: `Queue received no messages for ${props.noMessagesPeriod.toHumanString()}.`,
|
|
163
|
+
metric: props.queue.metric("NumberOfMessagesSent", {
|
|
164
|
+
statistic: "Sum",
|
|
165
|
+
period: props.noMessagesPeriod
|
|
166
|
+
}),
|
|
167
|
+
threshold: 0,
|
|
168
|
+
evaluationPeriods: 1,
|
|
169
|
+
comparisonOperator: ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
170
|
+
treatMissingData: TreatMissingData.BREACHING
|
|
171
|
+
});
|
|
172
|
+
noMessages.addAlarmAction(new SnsAction(queueTopic));
|
|
173
|
+
}
|
|
174
|
+
if (props.noConsumersPeriod) {
|
|
175
|
+
const noConsumers = new Alarm(this, "NoConsumersAlarm", {
|
|
176
|
+
alarmDescription: `Queue had no consumers for ${props.noConsumersPeriod.toHumanString()}.`,
|
|
177
|
+
metric: props.queue.metric("NumberOfMessagesReceived", {
|
|
178
|
+
statistic: "Sum",
|
|
179
|
+
period: props.noConsumersPeriod
|
|
180
|
+
}),
|
|
181
|
+
threshold: 0,
|
|
182
|
+
evaluationPeriods: 1,
|
|
183
|
+
comparisonOperator: ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
184
|
+
treatMissingData: TreatMissingData.BREACHING
|
|
185
|
+
});
|
|
186
|
+
noConsumers.addAlarmAction(new SnsAction(queueTopic));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// packages/cdk-constructs/src/sqsWithDlq.ts
|
|
192
|
+
import { Duration } from "aws-cdk-lib";
|
|
193
|
+
import {
|
|
194
|
+
SqsEventSource
|
|
195
|
+
} from "aws-cdk-lib/aws-lambda-event-sources";
|
|
196
|
+
import { Queue, QueueEncryption } from "aws-cdk-lib/aws-sqs";
|
|
197
|
+
import { Construct as Construct3 } from "constructs";
|
|
198
|
+
|
|
199
|
+
class SqsWithDlq extends Construct3 {
|
|
200
|
+
queue;
|
|
201
|
+
dlq;
|
|
202
|
+
constructor(scope, id, props = {}) {
|
|
203
|
+
super(scope, id);
|
|
204
|
+
this.dlq = new Queue(this, "Dlq", {
|
|
205
|
+
fifo: props.queue?.fifo,
|
|
206
|
+
contentBasedDeduplication: props.queue?.contentBasedDeduplication,
|
|
207
|
+
deduplicationScope: props.queue?.deduplicationScope,
|
|
208
|
+
encryption: QueueEncryption.SQS_MANAGED,
|
|
209
|
+
enforceSSL: true,
|
|
210
|
+
retentionPeriod: Duration.days(14),
|
|
211
|
+
...props?.dlq
|
|
212
|
+
});
|
|
213
|
+
this.queue = new Queue(this, "Queue", {
|
|
214
|
+
encryption: QueueEncryption.SQS_MANAGED,
|
|
215
|
+
enforceSSL: true,
|
|
216
|
+
retentionPeriod: Duration.days(14),
|
|
217
|
+
...props.queue,
|
|
218
|
+
deadLetterQueue: {
|
|
219
|
+
queue: this.dlq,
|
|
220
|
+
maxReceiveCount: 5,
|
|
221
|
+
...props.queue?.deadLetterQueue
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
static asLambdaInput(props) {
|
|
226
|
+
const { lambda, batching, ...sqsProps } = props;
|
|
227
|
+
const handlerTimeout = lambda.timeout ?? Duration.seconds(3);
|
|
228
|
+
const sqs = new SqsWithDlq(lambda, "Input", {
|
|
229
|
+
...sqsProps,
|
|
230
|
+
queue: {
|
|
231
|
+
visibilityTimeout: Duration.seconds(Math.min(handlerTimeout.toSeconds() * 6, 43200)),
|
|
232
|
+
...sqsProps.queue
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
lambda.addEventSource(new SqsEventSource(sqs.queue, {
|
|
236
|
+
...batching,
|
|
237
|
+
reportBatchItemFailures: true,
|
|
238
|
+
enabled: props.disabled !== true
|
|
239
|
+
}));
|
|
240
|
+
return sqs;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export {
|
|
244
|
+
SqsWithDlq,
|
|
245
|
+
EmailAlarms,
|
|
246
|
+
CloudFrontAccessLoggingSettings
|
|
247
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@beesolve/cdk-constructs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"homepage": "https://github.com/beesolve/packages/tree/main/packages/cdk-constructs#readme",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/beesolve/packages.git"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"type-check": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"typescript": "catalog:"
|
|
19
|
+
},
|
|
20
|
+
"peerDependenciesMeta": {
|
|
21
|
+
"typescript": {
|
|
22
|
+
"optional": true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"aws-cdk-lib": "catalog:",
|
|
27
|
+
"constructs": "catalog:",
|
|
28
|
+
"@beesolve/helpers": "workspace:*"
|
|
29
|
+
},
|
|
30
|
+
"type": "module",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"module": "./dist/index.js",
|
|
41
|
+
"types": "./dist/index.d.ts"
|
|
42
|
+
}
|