@rio-cloud/cdk-v2-constructs 6.15.0 → 6.16.1
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/.jsii +428 -47
- package/docs/API.md +544 -8
- package/docs/changelog.md +19 -0
- package/esbuild.mjs +4 -0
- package/lib/contributions/team-transport-two/pipeline/buildspecs.js +4 -1
- package/lib/contributions/team-transport-two/pipeline/pipeline-stack.js +2 -2
- package/lib/fargate/rio-fargate-service.d.ts +20 -2
- package/lib/fargate/rio-fargate-service.js +31 -11
- package/lib/index.d.ts +2 -0
- package/lib/index.js +4 -2
- package/lib/kafka/kafka-event-spec.d.ts +1 -1
- package/lib/kafka/kafka-event-spec.js +2 -2
- package/lib/kafka/kafka-topic.d.ts +2 -2
- package/lib/kafka/kafka-topic.js +1 -1
- package/lib/ses/helper.d.ts +24 -0
- package/lib/ses/helper.js +44 -0
- package/lib/ses/index.d.ts +1 -0
- package/lib/ses/index.js +18 -0
- package/lib/ses/lambda/ses-logger.cjs +50 -0
- package/lib/ses/lambda/ses-logger.d.ts +2 -0
- package/lib/ses/lambda/ses-logger.js +28 -0
- package/lib/ses/ses-observability.d.ts +63 -0
- package/lib/ses/ses-observability.js +225 -0
- package/package.json +1 -1
- package/version.json +1 -1
package/lib/ses/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ses-observability"), exports);
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxzREFBb0MiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL3Nlcy1vYnNlcnZhYmlsaXR5JzsiXX0=
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ses/lambda/ses-logger.ts
|
|
21
|
+
var ses_logger_exports = {};
|
|
22
|
+
__export(ses_logger_exports, {
|
|
23
|
+
handler: () => handler
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(ses_logger_exports);
|
|
26
|
+
var handler = async (event) => {
|
|
27
|
+
try {
|
|
28
|
+
const perEmailEvents = event.Records.map(({ Sns, ...rest }) => ({
|
|
29
|
+
...event,
|
|
30
|
+
Records: void 0,
|
|
31
|
+
Record: {
|
|
32
|
+
...rest,
|
|
33
|
+
Sns: {
|
|
34
|
+
...Sns,
|
|
35
|
+
Message: JSON.parse(Sns.Message)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}));
|
|
39
|
+
perEmailEvents.forEach((perEmailEvent) => {
|
|
40
|
+
console.log(perEmailEvent);
|
|
41
|
+
});
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.error(err);
|
|
44
|
+
console.log(event);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
48
|
+
0 && (module.exports = {
|
|
49
|
+
handler
|
|
50
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handler = void 0;
|
|
4
|
+
const handler = async (event) => {
|
|
5
|
+
try {
|
|
6
|
+
// Parse and write one log per event/email
|
|
7
|
+
const perEmailEvents = event.Records.map(({ Sns, ...rest }) => ({
|
|
8
|
+
...event,
|
|
9
|
+
Records: undefined,
|
|
10
|
+
Record: {
|
|
11
|
+
...rest,
|
|
12
|
+
Sns: {
|
|
13
|
+
...Sns,
|
|
14
|
+
Message: JSON.parse(Sns.Message),
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
perEmailEvents.forEach((perEmailEvent) => {
|
|
19
|
+
console.log(perEmailEvent);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
console.error(err);
|
|
24
|
+
console.log(event);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.handler = handler;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VzLWxvZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXMvbGFtYmRhL3Nlcy1sb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRU8sTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLEtBQWUsRUFBRSxFQUFFO0lBQy9DLElBQUksQ0FBQztRQUNILDBDQUEwQztRQUMxQyxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDOUQsR0FBRyxLQUFLO1lBQ1IsT0FBTyxFQUFFLFNBQVM7WUFDbEIsTUFBTSxFQUFFO2dCQUNOLEdBQUcsSUFBSTtnQkFDUCxHQUFHLEVBQUU7b0JBQ0gsR0FBRyxHQUFHO29CQUNOLE9BQU8sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQVc7aUJBQzNDO2FBQ0Y7U0FDRixDQUFDLENBQUMsQ0FBQztRQUNKLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRTtZQUN2QyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDckIsQ0FBQztBQUNILENBQUMsQ0FBQztBQXJCVyxRQUFBLE9BQU8sV0FxQmxCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU05TRXZlbnQgfSBmcm9tICdhd3MtbGFtYmRhJztcblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoZXZlbnQ6IFNOU0V2ZW50KSA9PiB7XG4gIHRyeSB7XG4gICAgLy8gUGFyc2UgYW5kIHdyaXRlIG9uZSBsb2cgcGVyIGV2ZW50L2VtYWlsXG4gICAgY29uc3QgcGVyRW1haWxFdmVudHMgPSBldmVudC5SZWNvcmRzLm1hcCgoeyBTbnMsIC4uLnJlc3QgfSkgPT4gKHtcbiAgICAgIC4uLmV2ZW50LFxuICAgICAgUmVjb3JkczogdW5kZWZpbmVkLFxuICAgICAgUmVjb3JkOiB7XG4gICAgICAgIC4uLnJlc3QsXG4gICAgICAgIFNuczoge1xuICAgICAgICAgIC4uLlNucyxcbiAgICAgICAgICBNZXNzYWdlOiBKU09OLnBhcnNlKFNucy5NZXNzYWdlKSBhcyBvYmplY3QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pKTtcbiAgICBwZXJFbWFpbEV2ZW50cy5mb3JFYWNoKChwZXJFbWFpbEV2ZW50KSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhwZXJFbWFpbEV2ZW50KTtcbiAgICB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgIGNvbnNvbGUubG9nKGV2ZW50KTtcbiAgfVxufTtcbiJdfQ==
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as ses from 'aws-cdk-lib/aws-ses';
|
|
2
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
3
|
+
import { Construct } from 'constructs';
|
|
4
|
+
export interface SesObservabilityProps {
|
|
5
|
+
/**
|
|
6
|
+
* The SES events to log.
|
|
7
|
+
*
|
|
8
|
+
* @default [EmailSendingEvent.DELIVERY, EmailSendingEvent.BOUNCE, EmailSendingEvent.COMPLAINT, EmailSendingEvent.REJECT]
|
|
9
|
+
*/
|
|
10
|
+
readonly loggedSesEvents?: ses.EmailSendingEvent[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* RioSesObservability
|
|
14
|
+
*
|
|
15
|
+
* This construct sets up observability for SES as defined by [ADR - SES domain reputation observability](https://confluence.collaboration-man.com/display/MAN/ADR+-+SES+domain+reputation+observability).
|
|
16
|
+
*
|
|
17
|
+
* # Warning
|
|
18
|
+
* This construct results in logging all sent emails including the recipient address into CloudWatch logs.
|
|
19
|
+
* As this is considered **PII**, this information MUST be handled accordingly.
|
|
20
|
+
* In particular, logs **MUST NOT** be sent to further third party services (e.g. Datadog) and the retention period for logs **MUST NOT** be extended.
|
|
21
|
+
*
|
|
22
|
+
* # Usage
|
|
23
|
+
* ## Default Configuration Set for Identity
|
|
24
|
+
*
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const rioSesObservability = new RioSesObservability(this, 'ConfigurationSet', {})
|
|
27
|
+
* const identity = new EmailIdentity(this, 'EmailIdentity', {
|
|
28
|
+
* identity: Identity.domain('example.com'),
|
|
29
|
+
* configurationSet: rioSesObservability.configurationSet,
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* ## Specifically using the configuration set per request
|
|
34
|
+
*
|
|
35
|
+
* This is ideal if you want to try out the construct first one some specific emails (e.g. during initial migration).
|
|
36
|
+
* The configuration set name is exported as an SSM parameter `/rio/config/ses-observability/configuration-set-name`.
|
|
37
|
+
* Thus, you can easily make it available as environment variable in your code.
|
|
38
|
+
*
|
|
39
|
+
* ```kotlin
|
|
40
|
+
* import com.amazonaws.services.simpleemail.model.SendEmailRequest
|
|
41
|
+
*
|
|
42
|
+
* val request = SendEmailRequest()
|
|
43
|
+
* .withConfigurationSetName(SSM_CONFIGURATION_SSM_PARAMETER_VALUE)
|
|
44
|
+
* ...
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* ## Automated event processing
|
|
48
|
+
*
|
|
49
|
+
* If you have specific needs for which you'd like to process the SNS events directly
|
|
50
|
+
* (e.g. automatically creating a suppression list from bounces), you can subscribe to the SNS topic.
|
|
51
|
+
* To enable this the SNS topic ARN is exported via Cloudformation as `RioSesObservabilityTopicArn`.
|
|
52
|
+
*/
|
|
53
|
+
export declare class SesObservability extends Construct {
|
|
54
|
+
static readonly CONFIGURATION_SET_NAME_SSM_PARAMETER = "/rio/config/ses-observability/configuration-set-name";
|
|
55
|
+
static readonly SNS_TOPIC_ARN_EXPORT_NAME = "RioSesObservabilityTopicArn";
|
|
56
|
+
readonly snsTopic: sns.Topic;
|
|
57
|
+
readonly configurationSet: ses.ConfigurationSet;
|
|
58
|
+
constructor(scope: Construct, id: string, props: SesObservabilityProps);
|
|
59
|
+
/**
|
|
60
|
+
* This function ensures that no PII is leaked to Datadog by adding a subscription filter to the log group of the lambda.
|
|
61
|
+
*/
|
|
62
|
+
private ensureNoSubscriptionFiltersOnLambdasLogGroup;
|
|
63
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SesObservability = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
8
|
+
const lambda = require("aws-cdk-lib/aws-lambda");
|
|
9
|
+
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
|
|
10
|
+
const ses = require("aws-cdk-lib/aws-ses");
|
|
11
|
+
const sns = require("aws-cdk-lib/aws-sns");
|
|
12
|
+
const snsSubscriptions = require("aws-cdk-lib/aws-sns-subscriptions");
|
|
13
|
+
const ssm = require("aws-cdk-lib/aws-ssm");
|
|
14
|
+
const cdk = require("aws-cdk-lib/core");
|
|
15
|
+
const constructs_1 = require("constructs");
|
|
16
|
+
const helper_1 = require("./helper");
|
|
17
|
+
const datadogv2_1 = require("../datadogv2");
|
|
18
|
+
const rio_landing_zone_1 = require("../rio-landing-zone");
|
|
19
|
+
/**
|
|
20
|
+
* RioSesObservability
|
|
21
|
+
*
|
|
22
|
+
* This construct sets up observability for SES as defined by [ADR - SES domain reputation observability](https://confluence.collaboration-man.com/display/MAN/ADR+-+SES+domain+reputation+observability).
|
|
23
|
+
*
|
|
24
|
+
* # Warning
|
|
25
|
+
* This construct results in logging all sent emails including the recipient address into CloudWatch logs.
|
|
26
|
+
* As this is considered **PII**, this information MUST be handled accordingly.
|
|
27
|
+
* In particular, logs **MUST NOT** be sent to further third party services (e.g. Datadog) and the retention period for logs **MUST NOT** be extended.
|
|
28
|
+
*
|
|
29
|
+
* # Usage
|
|
30
|
+
* ## Default Configuration Set for Identity
|
|
31
|
+
*
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const rioSesObservability = new RioSesObservability(this, 'ConfigurationSet', {})
|
|
34
|
+
* const identity = new EmailIdentity(this, 'EmailIdentity', {
|
|
35
|
+
* identity: Identity.domain('example.com'),
|
|
36
|
+
* configurationSet: rioSesObservability.configurationSet,
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* ## Specifically using the configuration set per request
|
|
41
|
+
*
|
|
42
|
+
* This is ideal if you want to try out the construct first one some specific emails (e.g. during initial migration).
|
|
43
|
+
* The configuration set name is exported as an SSM parameter `/rio/config/ses-observability/configuration-set-name`.
|
|
44
|
+
* Thus, you can easily make it available as environment variable in your code.
|
|
45
|
+
*
|
|
46
|
+
* ```kotlin
|
|
47
|
+
* import com.amazonaws.services.simpleemail.model.SendEmailRequest
|
|
48
|
+
*
|
|
49
|
+
* val request = SendEmailRequest()
|
|
50
|
+
* .withConfigurationSetName(SSM_CONFIGURATION_SSM_PARAMETER_VALUE)
|
|
51
|
+
* ...
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* ## Automated event processing
|
|
55
|
+
*
|
|
56
|
+
* If you have specific needs for which you'd like to process the SNS events directly
|
|
57
|
+
* (e.g. automatically creating a suppression list from bounces), you can subscribe to the SNS topic.
|
|
58
|
+
* To enable this the SNS topic ARN is exported via Cloudformation as `RioSesObservabilityTopicArn`.
|
|
59
|
+
*/
|
|
60
|
+
class SesObservability extends constructs_1.Construct {
|
|
61
|
+
constructor(scope, id, props) {
|
|
62
|
+
super(scope, id);
|
|
63
|
+
const accountId = aws_cdk_lib_1.Stack.of(this).account;
|
|
64
|
+
const accountName = rio_landing_zone_1.RioLandingZone.getAccountNameParameter(this);
|
|
65
|
+
const parameter = new ssm.StringParameter(this, 'ConfigurationSetName', {
|
|
66
|
+
parameterName: SesObservability.CONFIGURATION_SET_NAME_SSM_PARAMETER,
|
|
67
|
+
stringValue: 'rio-ses-observability-configuration-set',
|
|
68
|
+
});
|
|
69
|
+
this.snsTopic = new sns.Topic(this, 'SnsTopic', {
|
|
70
|
+
topicName: 'rio-ses-observability-topic',
|
|
71
|
+
});
|
|
72
|
+
this.configurationSet = new ses.ConfigurationSet(this, 'ConfigurationSet', {
|
|
73
|
+
configurationSetName: parameter.stringValue,
|
|
74
|
+
});
|
|
75
|
+
this.configurationSet.addEventDestination('EventDestination', {
|
|
76
|
+
configurationSetEventDestinationName: 'rio-ses-observability-event-destination',
|
|
77
|
+
destination: ses.EventDestination.snsTopic(this.snsTopic),
|
|
78
|
+
events: props.loggedSesEvents ?? [
|
|
79
|
+
ses.EmailSendingEvent.DELIVERY,
|
|
80
|
+
ses.EmailSendingEvent.BOUNCE,
|
|
81
|
+
ses.EmailSendingEvent.COMPLAINT,
|
|
82
|
+
ses.EmailSendingEvent.REJECT,
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
const logFunction = new lambda.Function(this, 'LogFunction', {
|
|
86
|
+
functionName: 'rio-ses-observability-log-function',
|
|
87
|
+
runtime: lambda.Runtime.NODEJS_20_X,
|
|
88
|
+
handler: 'index.handler',
|
|
89
|
+
logRetention: aws_logs_1.RetentionDays.THREE_MONTHS,
|
|
90
|
+
systemLogLevelV2: lambda.SystemLogLevel.WARN,
|
|
91
|
+
loggingFormat: lambda.LoggingFormat.JSON,
|
|
92
|
+
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda'), {
|
|
93
|
+
exclude: ['*.js', '*.d.ts'],
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
this.ensureNoSubscriptionFiltersOnLambdasLogGroup(logFunction);
|
|
97
|
+
this.snsTopic.addSubscription(new snsSubscriptions.LambdaSubscription(logFunction));
|
|
98
|
+
new cdk.CfnOutput(this, 'SnsTopicArn', {
|
|
99
|
+
value: this.snsTopic.topicArn,
|
|
100
|
+
exportName: SesObservability.SNS_TOPIC_ARN_EXPORT_NAME,
|
|
101
|
+
});
|
|
102
|
+
const notificationHandle = rio_landing_zone_1.RioLandingZone.getTeamAlertSlackChannelParameter(this);
|
|
103
|
+
new datadogv2_1.DatadogMonitor(this, 'QuotaMonitor', {
|
|
104
|
+
name: `${accountName} SES quota almost reached`,
|
|
105
|
+
serviceName: 'aws-ses',
|
|
106
|
+
monitorType: datadogv2_1.DatadogMonitorQueryAlertType.QUERY_ALERT,
|
|
107
|
+
query: `max(last_1h):max:aws.ses.sent_last_24_hours{account_id:${accountId}} / max:aws.ses.max_24_hour_send{account_id:${accountId}} > 0.8`,
|
|
108
|
+
message: (0, helper_1.trimIndent) `
|
|
109
|
+
You are almost using up you're maximum email sending quota per 24h.
|
|
110
|
+
Either [request an increase](https://docs.aws.amazon.com/ses/latest/dg/manage-sending-quotas-request-increase.html) for your quota by AWS or reduce the amount of emails sent.
|
|
111
|
+
You can find logs about all mails sent at \`${logFunction.logGroup.logGroupName}\`.
|
|
112
|
+
|
|
113
|
+
{{#is_alert}}@slack-${notificationHandle}{{/is_alert}}
|
|
114
|
+
{{#is_alert_recovery}}@slack-${notificationHandle}{{/is_alert_recovery}}
|
|
115
|
+
`,
|
|
116
|
+
priority: 4,
|
|
117
|
+
optionOverrides: {
|
|
118
|
+
thresholds: {
|
|
119
|
+
critical: 0.8,
|
|
120
|
+
warning: 0.7,
|
|
121
|
+
},
|
|
122
|
+
evaluationDelay: 900,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
new datadogv2_1.DatadogMonitor(this, 'EmailRejectedMonitor', {
|
|
126
|
+
name: `${accountName} SES Email Rejected`,
|
|
127
|
+
serviceName: 'aws-ses',
|
|
128
|
+
monitorType: datadogv2_1.DatadogMonitorQueryAlertType.QUERY_ALERT,
|
|
129
|
+
query: `sum(last_1h):max:aws.ses.rejects{account_id:${accountId}} > 0`,
|
|
130
|
+
message: (0, helper_1.trimIndent) `
|
|
131
|
+
SES [rejected](https://docs.aws.amazon.com/ses/latest/dg/monitor-sending-activity.html) sending at least one email.
|
|
132
|
+
Please investigate the root case, as this is not expected to happen in production ever.
|
|
133
|
+
You can find logs about all mails sent at \`${logFunction.logGroup.logGroupName}\`.
|
|
134
|
+
|
|
135
|
+
{{#is_alert}}@slack-${notificationHandle}{{/is_alert}}
|
|
136
|
+
`,
|
|
137
|
+
priority: 3,
|
|
138
|
+
optionOverrides: {
|
|
139
|
+
thresholds: {
|
|
140
|
+
critical: 0,
|
|
141
|
+
},
|
|
142
|
+
evaluationDelay: 900,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
new datadogv2_1.DatadogMonitor(this, 'ComplaintRateMonitor', {
|
|
146
|
+
name: `${accountName} SES reputation endangered: Complaint rate High`,
|
|
147
|
+
serviceName: 'aws-ses',
|
|
148
|
+
monitorType: datadogv2_1.DatadogMonitorQueryAlertType.QUERY_ALERT,
|
|
149
|
+
query: `max(last_1h):max:aws.ses.reputation_complaint_rate{account_id:${accountId} and not ses:*} > 0.001`,
|
|
150
|
+
message: (0, helper_1.trimIndent) `
|
|
151
|
+
Warning Threshold for Complaint rate {{#is_warning}}almost {{/is_warning}}reached (as defined in AWS).
|
|
152
|
+
|
|
153
|
+
Please reduce the number of complaints received for E-mails sent by your Account.
|
|
154
|
+
If this metric reaches \`0.5%\` the email sending capability of your account will be disabled by AWS.
|
|
155
|
+
You can find logs about all mails sent at \`${logFunction.logGroup.logGroupName}\`.
|
|
156
|
+
See [ADR - SES domain reputation observability](https://confluence.collaboration-man.com/display/MAN/ADR+-+SES+domain+reputation+observability).
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
{{#is_alert}}@slack-${notificationHandle}{{/is_alert}}
|
|
160
|
+
{{#is_alert_recovery}}@slack-${notificationHandle}{{/is_alert_recovery}}
|
|
161
|
+
`,
|
|
162
|
+
priority: 2,
|
|
163
|
+
optionOverrides: {
|
|
164
|
+
thresholds: {
|
|
165
|
+
critical: 0.001,
|
|
166
|
+
warning: 0.0008,
|
|
167
|
+
},
|
|
168
|
+
evaluationDelay: 900,
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
new datadogv2_1.DatadogMonitor(this, 'BounceRateMonitor', {
|
|
172
|
+
name: `${accountName} SES reputation endangered: Bounce Rate High`,
|
|
173
|
+
serviceName: 'aws-ses',
|
|
174
|
+
monitorType: datadogv2_1.DatadogMonitorQueryAlertType.QUERY_ALERT,
|
|
175
|
+
query: `max(last_1h):max:aws.ses.reputation_bounce_rate{account_id:${accountId} and not ses:*} > 0.05`,
|
|
176
|
+
message: (0, helper_1.trimIndent) `
|
|
177
|
+
Warning Threshold for Bounce rate {{#is_warning}}almost {{/is_warning}}reached (as defined in AWS).
|
|
178
|
+
|
|
179
|
+
Please reduce the number of bounces for E-mails sent by your Account.
|
|
180
|
+
If this metric reaches \`10%\` the email sending capability of your account will be disabled by AWS.
|
|
181
|
+
You can find logs about all mails sent at \`${logFunction.logGroup.logGroupName}\`.
|
|
182
|
+
See [ADR - SES domain reputation observability](https://confluence.collaboration-man.com/display/MAN/ADR+-+SES+domain+reputation+observability).
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
{{#is_alert}}@slack-${notificationHandle}{{/is_alert}}
|
|
186
|
+
{{#is_alert_recovery}}@slack-${notificationHandle}{{/is_alert_recovery}}
|
|
187
|
+
`,
|
|
188
|
+
priority: 2,
|
|
189
|
+
optionOverrides: {
|
|
190
|
+
thresholds: {
|
|
191
|
+
critical: 0.05,
|
|
192
|
+
warning: 0.04,
|
|
193
|
+
},
|
|
194
|
+
evaluationDelay: 900,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* This function ensures that no PII is leaked to Datadog by adding a subscription filter to the log group of the lambda.
|
|
200
|
+
*/
|
|
201
|
+
ensureNoSubscriptionFiltersOnLambdasLogGroup(logFunction) {
|
|
202
|
+
const stack = cdk.Stack.of(this);
|
|
203
|
+
stack.node.addValidation({
|
|
204
|
+
validate: () => {
|
|
205
|
+
const errors = [];
|
|
206
|
+
stack.node.findAll().forEach(node => {
|
|
207
|
+
if (node instanceof aws_logs_1.CfnSubscriptionFilter) {
|
|
208
|
+
const logGroupName = node.logGroupName;
|
|
209
|
+
if (logGroupName === logFunction.logGroup.logGroupName) {
|
|
210
|
+
errors.push('Subscription filters are not allowed ses-observability lambdas log group');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
return errors;
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
exports.SesObservability = SesObservability;
|
|
220
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
221
|
+
SesObservability[_a] = { fqn: "@rio-cloud/cdk-v2-constructs.SesObservability", version: "0.0.0" };
|
|
222
|
+
// ! changing these values is a breaking change for users
|
|
223
|
+
SesObservability.CONFIGURATION_SET_NAME_SSM_PARAMETER = '/rio/config/ses-observability/configuration-set-name';
|
|
224
|
+
SesObservability.SNS_TOPIC_ARN_EXPORT_NAME = 'RioSesObservabilityTopicArn';
|
|
225
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VzLW9ic2VydmFiaWxpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VzL3Nlcy1vYnNlcnZhYmlsaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkJBQTZCO0FBQzdCLDZDQUFvQztBQUNwQyxpREFBaUQ7QUFFakQsbURBQTRFO0FBQzVFLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0Msc0VBQXNFO0FBQ3RFLDJDQUEyQztBQUMzQyx3Q0FBd0M7QUFDeEMsMkNBQXVDO0FBQ3ZDLHFDQUFzQztBQUN0Qyw0Q0FBNEU7QUFDNUUsMERBQXFEO0FBWXJEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0NHO0FBQ0gsTUFBYSxnQkFBaUIsU0FBUSxzQkFBUztJQU83QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTRCO1FBQ3BFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakIsTUFBTSxTQUFTLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQ3pDLE1BQU0sV0FBVyxHQUFHLGlDQUFjLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFakUsTUFBTSxTQUFTLEdBQUcsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxzQkFBc0IsRUFBRTtZQUN0RSxhQUFhLEVBQUUsZ0JBQWdCLENBQUMsb0NBQW9DO1lBQ3BFLFdBQVcsRUFBRSx5Q0FBeUM7U0FDdkQsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUM5QyxTQUFTLEVBQUUsNkJBQTZCO1NBQ3pDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVB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QUFPLEVBQUUsSUFBSTtpQkFDZDtnQkFDRCxlQUFlLEVBQUUsR0FBRzthQUNyQjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLDRDQUE0QyxDQUFDLFdBQTJCO1FBQzlFLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLEtBQUssQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQ3ZCLFFBQVEsRUFBRSxHQUFHLEVBQUU7Z0JBQ2IsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO2dCQUM1QixLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDbEMsSUFBSSxJQUFJLFlBQVksZ0NBQXFCLEVBQUUsQ0FBQzt3QkFDMUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQzt3QkFDdkMsSUFBSSxZQUFZLEtBQUssV0FBVyxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQzs0QkFDdkQsTUFBTSxDQUFDLElBQUksQ0FBQywwRUFBMEUsQ0FBQyxDQUFDO3dCQUMxRixDQUFDO29CQUNILENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBaExILDRDQWlMQzs7O0FBaExDLHlEQUF5RDtBQUN6QyxxREFBb0MsR0FBRyxzREFBc0QsQ0FBQztBQUM5RiwwQ0FBeUIsR0FBRyw2QkFBNkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0IHsgQ2ZuU3Vic2NyaXB0aW9uRmlsdGVyLCBSZXRlbnRpb25EYXlzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgc2VzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zZXMnO1xuaW1wb3J0ICogYXMgc25zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zbnMnO1xuaW1wb3J0ICogYXMgc25zU3Vic2NyaXB0aW9ucyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zLXN1YnNjcmlwdGlvbnMnO1xuaW1wb3J0ICogYXMgc3NtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zc20nO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyB0cmltSW5kZW50IH0gZnJvbSAnLi9oZWxwZXInO1xuaW1wb3J0IHsgRGF0YWRvZ01vbml0b3IsIERhdGFkb2dNb25pdG9yUXVlcnlBbGVydFR5cGUgfSBmcm9tICcuLi9kYXRhZG9ndjInO1xuaW1wb3J0IHsgUmlvTGFuZGluZ1pvbmUgfSBmcm9tICcuLi9yaW8tbGFuZGluZy16b25lJztcblxuXG5leHBvcnQgaW50ZXJmYWNlIFNlc09ic2VydmFiaWxpdHlQcm9wcyB7XG4gIC8qKlxuICAgICAqIFRoZSBTRVMgZXZlbnRzIHRvIGxvZy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IFtFbWFpbFNlbmRpbmdFdmVudC5ERUxJVkVSWSwgRW1haWxTZW5kaW5nRXZlbnQuQk9VTkNFLCBFbWFpbFNlbmRpbmdFdmVudC5DT01QTEFJTlQsIEVtYWlsU2VuZGluZ0V2ZW50LlJFSkVDVF1cbiAgICAgKi9cbiAgcmVhZG9ubHkgbG9nZ2VkU2VzRXZlbnRzPzogc2VzLkVtYWlsU2VuZGluZ0V2ZW50W107XG59XG5cbi8qKlxuICogUmlvU2VzT2JzZXJ2YWJpbGl0eVxuICpcbiAqIFRoaXMgY29uc3RydWN0IHNldHMgdXAgb2JzZXJ2YWJpbGl0eSBmb3IgU0VTIGFzIGRlZmluZWQgYnkgW0FEUiAtIFNFUyBkb21haW4gcmVwdXRhdGlvbiBvYnNlcnZhYmlsaXR5XShodHRwczovL2NvbmZsdWVuY2UuY29sbGFib3JhdGlvbi1tYW4uY29tL2Rpc3BsYXkvTUFOL0FEUistK1NFUytkb21haW4rcmVwdXRhdGlvbitvYnNlcnZhYmlsaXR5KS5cbiAqXG4gKiAjIFdhcm5pbmdcbiAqIFRoaXMgY29uc3RydWN0IHJlc3VsdHMgaW4gbG9nZ2luZyBhbGwgc2VudCBlbWFpbHMgaW5jbHVkaW5nIHRoZSByZWNpcGllbnQgYWRkcmVzcyBpbnRvIENsb3VkV2F0Y2ggbG9ncy5cbiAqIEFzIHRoaXMgaXMgY29uc2lkZXJlZCAqKlBJSSoqLCB0aGlzIGluZm9ybWF0aW9uIE1VU1QgYmUgaGFuZGxlZCBhY2NvcmRpbmdseS5cbiAqIEluIHBhcnRpY3VsYXIsIGxvZ3MgKipNVVNUIE5PVCoqIGJlIHNlbnQgdG8gZnVydGhlciB0aGlyZCBwYXJ0eSBzZXJ2aWNlcyAoZS5nLiBEYXRhZG9nKSBhbmQgdGhlIHJldGVudGlvbiBwZXJpb2QgZm9yIGxvZ3MgKipNVVNUIE5PVCoqIGJlIGV4dGVuZGVkLlxuICpcbiAqICMgVXNhZ2VcbiAqICMjIERlZmF1bHQgQ29uZmlndXJhdGlvbiBTZXQgZm9yIElkZW50aXR5XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcmlvU2VzT2JzZXJ2YWJpbGl0eSA9IG5ldyBSaW9TZXNPYnNlcnZhYmlsaXR5KHRoaXMsICdDb25maWd1cmF0aW9uU2V0Jywge30pXG4gKiBjb25zdCBpZGVudGl0eSA9IG5ldyBFbWFpbElkZW50aXR5KHRoaXMsICdFbWFpbElkZW50aXR5Jywge1xuICogICAgIGlkZW50aXR5OiBJZGVudGl0eS5kb21haW4oJ2V4YW1wbGUuY29tJyksXG4gKiAgICAgY29uZmlndXJhdGlvblNldDogcmlvU2VzT2JzZXJ2YWJpbGl0eS5jb25maWd1cmF0aW9uU2V0LFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiAjIyBTcGVjaWZpY2FsbHkgdXNpbmcgdGhlIGNvbmZpZ3VyYXRpb24gc2V0IHBlciByZXF1ZXN0XG4gKlxuICogVGhpcyBpcyBpZGVhbCBpZiB5b3Ugd2FudCB0byB0cnkgb3V0IHRoZSBjb25zdHJ1Y3QgZmlyc3Qgb25lIHNvbWUgc3BlY2lmaWMgZW1haWxzIChlLmcuIGR1cmluZyBpbml0aWFsIG1pZ3JhdGlvbikuXG4gKiBUaGUgY29uZmlndXJhdGlvbiBzZXQgbmFtZSBpcyBleHBvcnRlZCBhcyBhbiBTU00gcGFyYW1ldGVyIGAvcmlvL2NvbmZpZy9zZXMtb2JzZXJ2YWJpbGl0eS9jb25maWd1cmF0aW9uLXNldC1uYW1lYC5cbiAqIFRodXMsIHlvdSBjYW4gZWFzaWx5IG1ha2UgaXQgYXZhaWxhYmxlIGFzIGVudmlyb25tZW50IHZhcmlhYmxlIGluIHlvdXIgY29kZS5cbiAqXG4gKiBgYGBrb3RsaW5cbiAqIGltcG9ydCBjb20uYW1hem9uYXdzLnNlcnZpY2VzLnNpbXBsZWVtYWlsLm1vZGVsLlNlbmRFbWFpbFJlcXVlc3RcbiAqXG4gKiB2YWwgcmVxdWVzdCA9IFNlbmRFbWFpbFJlcXVlc3QoKVxuICogICAgICAgICAgICAgICAgIC53aXRoQ29uZmlndXJhdGlvblNldE5hbWUoU1NNX0NPTkZJR1VSQVRJT05fU1NNX1BBUkFNRVRFUl9WQUxVRSlcbiAqICAgICAgICAgICAgICAgICAuLi5cbiAqIGBgYFxuICpcbiAqICMjIEF1dG9tYXRlZCBldmVudCBwcm9jZXNzaW5nXG4gKlxuICogSWYgeW91IGhhdmUgc3BlY2lmaWMgbmVlZHMgZm9yIHdoaWNoIHlvdSdkIGxpa2UgdG8gcHJvY2VzcyB0aGUgU05TIGV2ZW50cyBkaXJlY3RseVxuICogKGUuZy4gYXV0b21hdGljYWxseSBjcmVhdGluZyBhIHN1cHByZXNzaW9uIGxpc3QgZnJvbSBib3VuY2VzKSwgeW91IGNhbiBzdWJzY3JpYmUgdG8gdGhlIFNOUyB0b3BpYy5cbiAqIFRvIGVuYWJsZSB0aGlzIHRoZSBTTlMgdG9waWMgQVJOIGlzIGV4cG9ydGVkIHZpYSBDbG91ZGZvcm1hdGlvbiBhcyBgUmlvU2VzT2JzZXJ2YWJpbGl0eVRvcGljQXJuYC5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc09ic2VydmFiaWxpdHkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvLyAhIGNoYW5naW5nIHRoZXNlIHZhbHVlcyBpcyBhIGJyZWFraW5nIGNoYW5nZSBmb3IgdXNlcnNcbiAgc3RhdGljIHJlYWRvbmx5IENPTkZJR1VSQVRJT05fU0VUX05BTUVfU1NNX1BBUkFNRVRFUiA9ICcvcmlvL2NvbmZpZy9zZXMtb2JzZXJ2YWJpbGl0eS9jb25maWd1cmF0aW9uLXNldC1uYW1lJztcbiAgc3RhdGljIHJlYWRvbmx5IFNOU19UT1BJQ19BUk5fRVhQT1JUX05BTUUgPSAnUmlvU2VzT2JzZXJ2YWJpbGl0eVRvcGljQXJuJztcbiAgcmVhZG9ubHkgc25zVG9waWM6IHNucy5Ub3BpYztcbiAgcmVhZG9ubHkgY29uZmlndXJhdGlvblNldDogc2VzLkNvbmZpZ3VyYXRpb25TZXQ7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFNlc09ic2VydmFiaWxpdHlQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgY29uc3QgYWNjb3VudElkID0gU3RhY2sub2YodGhpcykuYWNjb3VudDtcbiAgICBjb25zdCBhY2NvdW50TmFtZSA9IFJpb0xhbmRpbmdab25lLmdldEFjY291bnROYW1lUGFyYW1ldGVyKHRoaXMpO1xuXG4gICAgY29uc3QgcGFyYW1ldGVyID0gbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcywgJ0NvbmZpZ3VyYXRpb25TZXROYW1lJywge1xuICAgICAgcGFyYW1ldGVyTmFtZTogU2VzT2JzZXJ2YWJpbGl0eS5DT05GSUdVUkFUSU9OX1NFVF9OQU1FX1NTTV9QQVJBTUVURVIsXG4gICAgICBzdHJpbmdWYWx1ZTogJ3Jpby1zZXMtb2JzZXJ2YWJpbGl0eS1jb25maWd1cmF0aW9uLXNldCcsXG4gICAgfSk7XG5cbiAgICB0aGlzLnNuc1RvcGljID0gbmV3IHNucy5Ub3BpYyh0aGlzLCAnU25zVG9waWMnLCB7XG4gICAgICB0b3BpY05hbWU6ICdyaW8tc2VzLW9ic2VydmFiaWxpdHktdG9waWMnLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jb25maWd1cmF0aW9uU2V0ID0gbmV3IHNlcy5Db25maWd1cmF0aW9uU2V0KHRoaXMsICdDb25maWd1cmF0aW9uU2V0Jywge1xuICAgICAgY29uZmlndXJhdGlvblNldE5hbWU6IHBhcmFtZXRlci5zdHJpbmdWYWx1ZSxcbiAgICB9KTtcblxuICAgIHRoaXMuY29uZmlndXJhdGlvblNldC5hZGRFdmVudERlc3RpbmF0aW9uKCdFdmVudERlc3RpbmF0aW9uJywge1xuICAgICAgY29uZmlndXJhdGlvblNldEV2ZW50RGVzdGluYXRpb25OYW1lOiAncmlvLXNlcy1vYnNlcnZhYmlsaXR5LWV2ZW50LWRlc3RpbmF0aW9uJyxcbiAgICAgIGRlc3RpbmF0aW9uOiBzZXMuRXZlbnREZXN0aW5hdGlvbi5zbnNUb3BpYyh0aGlzLnNuc1RvcGljKSxcbiAgICAgIGV2ZW50czogcHJvcHMubG9nZ2VkU2VzRXZlbnRzID8/IFtcbiAgICAgICAgc2VzLkVtYWlsU2VuZGluZ0V2ZW50LkRFTElWRVJZLFxuICAgICAgICBzZXMuRW1haWxTZW5kaW5nRXZlbnQuQk9VTkNFLFxuICAgICAgICBzZXMuRW1haWxTZW5kaW5nRXZlbnQuQ09NUExBSU5ULFxuICAgICAgICBzZXMuRW1haWxTZW5kaW5nRXZlbnQuUkVKRUNULFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGxvZ0Z1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCAnTG9nRnVuY3Rpb24nLCB7XG4gICAgICBmdW5jdGlvbk5hbWU6ICdyaW8tc2VzLW9ic2VydmFiaWxpdHktbG9nLWZ1bmN0aW9uJyxcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yMF9YLFxuICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgbG9nUmV0ZW50aW9uOiBSZXRlbnRpb25EYXlzLlRIUkVFX01PTlRIUyxcbiAgICAgIHN5c3RlbUxvZ0xldmVsVjI6IGxhbWJkYS5TeXN0ZW1Mb2dMZXZlbC5XQVJOLFxuICAgICAgbG9nZ2luZ0Zvcm1hdDogbGFtYmRhLkxvZ2dpbmdGb3JtYXQuSlNPTixcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnbGFtYmRhJyksIHtcbiAgICAgICAgZXhjbHVkZTogWycqLmpzJywgJyouZC50cyddLFxuICAgICAgfSksXG4gICAgfSk7XG4gICAgdGhpcy5lbnN1cmVOb1N1YnNjcmlwdGlvbkZpbHRlcnNPbkxhbWJkYXNMb2dHcm91cChsb2dGdW5jdGlvbik7XG5cbiAgICB0aGlzLnNuc1RvcGljLmFkZFN1YnNjcmlwdGlvbihuZXcgc25zU3Vic2NyaXB0aW9ucy5MYW1iZGFTdWJzY3JpcHRpb24obG9nRnVuY3Rpb24pKTtcblxuICAgIG5ldyBjZGsuQ2ZuT3V0cHV0KHRoaXMsICdTbnNUb3BpY0FybicsIHtcbiAgICAgIHZhbHVlOiB0aGlzLnNuc1RvcGljLnRvcGljQXJuLFxuICAgICAgZXhwb3J0TmFtZTogU2VzT2JzZXJ2YWJpbGl0eS5TTlNfVE9QSUNfQVJOX0VYUE9SVF9OQU1FLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgbm90aWZpY2F0aW9uSGFuZGxlID0gUmlvTGFuZGluZ1pvbmUuZ2V0VGVhbUFsZXJ0U2xhY2tDaGFubmVsUGFyYW1ldGVyKHRoaXMpO1xuXG4gICAgbmV3IERhdGFkb2dNb25pdG9yKHRoaXMsICdRdW90YU1vbml0b3InLCB7XG4gICAgICBuYW1lOiBgJHthY2NvdW50TmFtZX0gU0VTIHF1b3RhIGFsbW9zdCByZWFjaGVkYCxcbiAgICAgIHNlcnZpY2VOYW1lOiAnYXdzLXNlcycsXG4gICAgICBtb25pdG9yVHlwZTogRGF0YWRvZ01vbml0b3JRdWVyeUFsZXJ0VHlwZS5RVUVSWV9BTEVSVCxcbiAgICAgIHF1ZXJ5OiBgbWF4KGxhc3RfMWgpOm1heDphd3Muc2VzLnNlbnRfbGFzdF8yNF9ob3Vyc3thY2NvdW50X2lkOiR7YWNjb3VudElkfX0gLyBtYXg6YXdzLnNlcy5tYXhfMjRfaG91cl9zZW5ke2FjY291bnRfaWQ6JHthY2NvdW50SWR9fSA+IDAuOGAsXG4gICAgICBtZXNzYWdlOiB0cmltSW5kZW50YFxuICAgICAgICBZb3UgYXJlIGFsbW9zdCB1c2luZyB1cCB5b3UncmUgbWF4aW11bSBlbWFpbCBzZW5kaW5nIHF1b3RhIHBlciAyNGguIFxuICAgICAgICBFaXRoZXIgW3JlcXVlc3QgYW4gaW5jcmVhc2VdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9zZXMvbGF0ZXN0L2RnL21hbmFnZS1zZW5kaW5nLXF1b3Rhcy1yZXF1ZXN0LWluY3JlYXNlLmh0bWwpIGZvciB5b3VyIHF1b3RhIGJ5IEFXUyBvciByZWR1Y2UgdGhlIGFtb3VudCBvZiBlbWFpbHMgc2VudC5cbiAgICAgICAgWW91IGNhbiBmaW5kIGxvZ3MgYWJvdXQgYWxsIG1haWxzIHNlbnQgYXQgXFxgJHtsb2dGdW5jdGlvbi5sb2dHcm91cC5sb2dHcm91cE5hbWV9XFxgLlxuICAgICAgICBcbiAgICAgICAge3sjaXNfYWxlcnR9fUBzbGFjay0ke25vdGlmaWNhdGlvbkhhbmRsZX17ey9pc19hbGVydH19XG4gICAgICAgIHt7I2lzX2FsZXJ0X3JlY292ZXJ5fX1Ac2xhY2stJHtub3RpZmljYXRpb25IYW5kbGV9e3svaXNfYWxlcnRfcmVjb3Zlcnl9fVxuICAgICAgICBgLFxuICAgICAgcHJpb3JpdHk6IDQsXG4gICAgICBvcHRpb25PdmVycmlkZXM6IHtcbiAgICAgICAgdGhyZXNob2xkczoge1xuICAgICAgICAgIGNyaXRpY2FsOiAwLjgsXG4gICAgICAgICAgd2FybmluZzogMC43LFxuICAgICAgICB9LFxuICAgICAgICBldmFsdWF0aW9uRGVsYXk6IDkwMCxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBuZXcgRGF0YWRvZ01vbml0b3IodGhpcywgJ0VtYWlsUmVqZWN0ZWRNb25pdG9yJywge1xuICAgICAgbmFtZTogYCR7YWNjb3VudE5hbWV9IFNFUyBFbWFpbCBSZWplY3RlZGAsXG4gICAgICBzZXJ2aWNlTmFtZTogJ2F3cy1zZXMnLFxuICAgICAgbW9uaXRvclR5cGU6IERhdGFkb2dNb25pdG9yUXVlcnlBbGVydFR5cGUuUVVFUllfQUxFUlQsXG4gICAgICBxdWVyeTogYHN1bShsYXN0XzFoKTptYXg6YXdzLnNlcy5yZWplY3Rze2FjY291bnRfaWQ6JHthY2NvdW50SWR9fSA+IDBgLFxuICAgICAgbWVzc2FnZTogdHJpbUluZGVudGBcbiAgICAgICAgU0VTIFtyZWplY3RlZF0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Nlcy9sYXRlc3QvZGcvbW9uaXRvci1zZW5kaW5nLWFjdGl2aXR5Lmh0bWwpIHNlbmRpbmcgYXQgbGVhc3Qgb25lIGVtYWlsLlxuICAgICAgICBQbGVhc2UgaW52ZXN0aWdhdGUgdGhlIHJvb3QgY2FzZSwgYXMgdGhpcyBpcyBub3QgZXhwZWN0ZWQgdG8gaGFwcGVuIGluIHByb2R1Y3Rpb24gZXZlci5cbiAgICAgICAgWW91IGNhbiBmaW5kIGxvZ3MgYWJvdXQgYWxsIG1haWxzIHNlbnQgYXQgXFxgJHtsb2dGdW5jdGlvbi5sb2dHcm91cC5sb2dHcm91cE5hbWV9XFxgLlxuICAgICAgICBcbiAgICAgICAge3sjaXNfYWxlcnR9fUBzbGFjay0ke25vdGlmaWNhdGlvbkhhbmRsZX17ey9pc19hbGVydH19XG4gICAgICAgIGAsXG4gICAgICBwcmlvcml0eTogMyxcbiAgICAgIG9wdGlvbk92ZXJyaWRlczoge1xuICAgICAgICB0aHJlc2hvbGRzOiB7XG4gICAgICAgICAgY3JpdGljYWw6IDAsXG4gICAgICAgIH0sXG4gICAgICAgIGV2YWx1YXRpb25EZWxheTogOTAwLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIG5ldyBEYXRhZG9nTW9uaXRvcih0aGlzLCAnQ29tcGxhaW50UmF0ZU1vbml0b3InLCB7XG4gICAgICBuYW1lOiBgJHthY2NvdW50TmFtZX0gU0VTIHJlcHV0YXRpb24gZW5kYW5nZXJlZDogQ29tcGxhaW50IHJhdGUgSGlnaGAsXG4gICAgICBzZXJ2aWNlTmFtZTogJ2F3cy1zZXMnLFxuICAgICAgbW9uaXRvclR5cGU6IERhdGFkb2dNb25pdG9yUXVlcnlBbGVydFR5cGUuUVVFUllfQUxFUlQsXG4gICAgICBxdWVyeTogYG1heChsYXN0XzFoKTptYXg6YXdzLnNlcy5yZXB1dGF0aW9uX2NvbXBsYWludF9yYXRle2FjY291bnRfaWQ6JHthY2NvdW50SWR9IGFuZCBub3Qgc2VzOip9ID4gMC4wMDFgLFxuICAgICAgbWVzc2FnZTogdHJpbUluZGVudGBcbiAgICAgICAgV2FybmluZyBUaHJlc2hvbGQgZm9yIENvbXBsYWludCByYXRlIHt7I2lzX3dhcm5pbmd9fWFsbW9zdCB7ey9pc193YXJuaW5nfX1yZWFjaGVkIChhcyBkZWZpbmVkIGluIEFXUykuXG4gICAgICAgIFxuICAgICAgICBQbGVhc2UgcmVkdWNlIHRoZSBudW1iZXIgb2YgY29tcGxhaW50cyByZWNlaXZlZCBmb3IgRS1tYWlscyBzZW50IGJ5IHlvdXIgQWNjb3VudC5cbiAgICAgICAgSWYgdGhpcyBtZXRyaWMgcmVhY2hlcyBcXGAwLjUlXFxgIHRoZSBlbWFpbCBzZW5kaW5nIGNhcGFiaWxpdHkgb2YgeW91ciBhY2NvdW50IHdpbGwgYmUgZGlzYWJsZWQgYnkgQVdTLlxuICAgICAgICBZb3UgY2FuIGZpbmQgbG9ncyBhYm91dCBhbGwgbWFpbHMgc2VudCBhdCBcXGAke2xvZ0Z1bmN0aW9uLmxvZ0dyb3VwLmxvZ0dyb3VwTmFtZX1cXGAuXG4gICAgICAgIFNlZSBbQURSIC0gU0VTIGRvbWFpbiByZXB1dGF0aW9uIG9ic2VydmFiaWxpdHldKGh0dHBzOi8vY29uZmx1ZW5jZS5jb2xsYWJvcmF0aW9uLW1hbi5jb20vZGlzcGxheS9NQU4vQURSKy0rU0VTK2RvbWFpbityZXB1dGF0aW9uK29ic2VydmFiaWxpdHkpLlxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIHt7I2lzX2FsZXJ0fX1Ac2xhY2stJHtub3RpZmljYXRpb25IYW5kbGV9e3svaXNfYWxlcnR9fVxuICAgICAgICB7eyNpc19hbGVydF9yZWNvdmVyeX19QHNsYWNrLSR7bm90aWZpY2F0aW9uSGFuZGxlfXt7L2lzX2FsZXJ0X3JlY292ZXJ5fX1cbiAgICAgICAgYCxcbiAgICAgIHByaW9yaXR5OiAyLFxuICAgICAgb3B0aW9uT3ZlcnJpZGVzOiB7XG4gICAgICAgIHRocmVzaG9sZHM6IHtcbiAgICAgICAgICBjcml0aWNhbDogMC4wMDEsXG4gICAgICAgICAgd2FybmluZzogMC4wMDA4LFxuICAgICAgICB9LFxuICAgICAgICBldmFsdWF0aW9uRGVsYXk6IDkwMCxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBuZXcgRGF0YWRvZ01vbml0b3IodGhpcywgJ0JvdW5jZVJhdGVNb25pdG9yJywge1xuICAgICAgbmFtZTogYCR7YWNjb3VudE5hbWV9IFNFUyByZXB1dGF0aW9uIGVuZGFuZ2VyZWQ6IEJvdW5jZSBSYXRlIEhpZ2hgLFxuICAgICAgc2VydmljZU5hbWU6ICdhd3Mtc2VzJyxcbiAgICAgIG1vbml0b3JUeXBlOiBEYXRhZG9nTW9uaXRvclF1ZXJ5QWxlcnRUeXBlLlFVRVJZX0FMRVJULFxuICAgICAgcXVlcnk6IGBtYXgobGFzdF8xaCk6bWF4OmF3cy5zZXMucmVwdXRhdGlvbl9ib3VuY2VfcmF0ZXthY2NvdW50X2lkOiR7YWNjb3VudElkfSBhbmQgbm90IHNlczoqfSA+IDAuMDVgLFxuICAgICAgbWVzc2FnZTogdHJpbUluZGVudGBcbiAgICAgICAgV2FybmluZyBUaHJlc2hvbGQgZm9yIEJvdW5jZSByYXRlIHt7I2lzX3dhcm5pbmd9fWFsbW9zdCB7ey9pc193YXJuaW5nfX1yZWFjaGVkIChhcyBkZWZpbmVkIGluIEFXUykuXG4gICAgICAgIFxuICAgICAgICBQbGVhc2UgcmVkdWNlIHRoZSBudW1iZXIgb2YgYm91bmNlcyBmb3IgRS1tYWlscyBzZW50IGJ5IHlvdXIgQWNjb3VudC5cbiAgICAgICAgSWYgdGhpcyBtZXRyaWMgcmVhY2hlcyBcXGAxMCVcXGAgdGhlIGVtYWlsIHNlbmRpbmcgY2FwYWJpbGl0eSBvZiB5b3VyIGFjY291bnQgd2lsbCBiZSBkaXNhYmxlZCBieSBBV1MuXG4gICAgICAgIFlvdSBjYW4gZmluZCBsb2dzIGFib3V0IGFsbCBtYWlscyBzZW50IGF0IFxcYCR7bG9nRnVuY3Rpb24ubG9nR3JvdXAubG9nR3JvdXBOYW1lfVxcYC5cbiAgICAgICAgU2VlIFtBRFIgLSBTRVMgZG9tYWluIHJlcHV0YXRpb24gb2JzZXJ2YWJpbGl0eV0oaHR0cHM6Ly9jb25mbHVlbmNlLmNvbGxhYm9yYXRpb24tbWFuLmNvbS9kaXNwbGF5L01BTi9BRFIrLStTRVMrZG9tYWluK3JlcHV0YXRpb24rb2JzZXJ2YWJpbGl0eSkuXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAge3sjaXNfYWxlcnR9fUBzbGFjay0ke25vdGlmaWNhdGlvbkhhbmRsZX17ey9pc19hbGVydH19XG4gICAgICAgIHt7I2lzX2FsZXJ0X3JlY292ZXJ5fX1Ac2xhY2stJHtub3RpZmljYXRpb25IYW5kbGV9e3svaXNfYWxlcnRfcmVjb3Zlcnl9fVxuICAgICAgICBgLFxuICAgICAgcHJpb3JpdHk6IDIsXG4gICAgICBvcHRpb25PdmVycmlkZXM6IHtcbiAgICAgICAgdGhyZXNob2xkczoge1xuICAgICAgICAgIGNyaXRpY2FsOiAwLjA1LFxuICAgICAgICAgIHdhcm5pbmc6IDAuMDQsXG4gICAgICAgIH0sXG4gICAgICAgIGV2YWx1YXRpb25EZWxheTogOTAwLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGVuc3VyZXMgdGhhdCBubyBQSUkgaXMgbGVha2VkIHRvIERhdGFkb2cgYnkgYWRkaW5nIGEgc3Vic2NyaXB0aW9uIGZpbHRlciB0byB0aGUgbG9nIGdyb3VwIG9mIHRoZSBsYW1iZGEuXG4gICAqL1xuICBwcml2YXRlIGVuc3VyZU5vU3Vic2NyaXB0aW9uRmlsdGVyc09uTGFtYmRhc0xvZ0dyb3VwKGxvZ0Z1bmN0aW9uOiBOb2RlanNGdW5jdGlvbikge1xuICAgIGNvbnN0IHN0YWNrID0gY2RrLlN0YWNrLm9mKHRoaXMpO1xuICAgIHN0YWNrLm5vZGUuYWRkVmFsaWRhdGlvbih7XG4gICAgICB2YWxpZGF0ZTogKCkgPT4ge1xuICAgICAgICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIHN0YWNrLm5vZGUuZmluZEFsbCgpLmZvckVhY2gobm9kZSA9PiB7XG4gICAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDZm5TdWJzY3JpcHRpb25GaWx0ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvZ0dyb3VwTmFtZSA9IG5vZGUubG9nR3JvdXBOYW1lO1xuICAgICAgICAgICAgaWYgKGxvZ0dyb3VwTmFtZSA9PT0gbG9nRnVuY3Rpb24ubG9nR3JvdXAubG9nR3JvdXBOYW1lKSB7XG4gICAgICAgICAgICAgIGVycm9ycy5wdXNoKCdTdWJzY3JpcHRpb24gZmlsdGVycyBhcmUgbm90IGFsbG93ZWQgc2VzLW9ic2VydmFiaWxpdHkgbGFtYmRhcyBsb2cgZ3JvdXAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZXJyb3JzO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufSJdfQ==
|
package/package.json
CHANGED
package/version.json
CHANGED