@mavogel/awscdk-rootmail 0.0.17 → 0.0.19
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 +57 -19
- package/API.md +117 -2
- package/README.md +91 -2
- package/docs/img/cloudformation-tpl-min.png +0 -0
- package/integ-tests/functions/custom-ses-receive-function.ts +92 -0
- package/integ-tests/integ.rootmail-custom-santa.ts +143 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/RootmailIntegTestStack.assets.json +162 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/RootmailIntegTestStack.template.json +4541 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.assets.json +32 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.template.json +249 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.0649b5bfaa322d6bd173d2daef3177389cf0778b556b300ac6bf451704cc3a49/index.js +37981 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.157ba1713f7224463b621261792d18081588ff306a9bc3f75e6c468fabbe1a60/index.js +106 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.4c079063901e6478dbb5ace19e3123641ebf0da2ab648ecf52079c5bec154196/index.js +215 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.53e8368959effe94a6e51bef9c7c5bf0eaf5c4d64eece81632ca62aa34517978.bundle/index.js +31981 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.d.ts +14 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.5cc92ed0cea39e2b8de2dbc527dfb5980a3af9564bd1084d840b9787c7d0467e/index.js +1 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.78b64aaf9aebb4eacbdd42197be10e9d5894360a642f7dcf79aeb84bb3552377/index.js +61 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.7e8a681794eff5fda1841caa360113df5488ecf944055a69b8f1e5a687e269f5/index.js +83 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.9572b451243318765beb576ae7528096b3879783dbaab795c02c01d7f4e83438/index.js +47 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.b8448324ef2c7d5bfa362722df2d397079d5aabaae2749f09180ac5bedfa5c89/index.js +105 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.d2b520d86fd9d964c83dc0d5ce2e4456dbde5fa7ae0c791a71865cbdfe2fb855/index.js +85 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/cfn-response.js +1 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/consts.js +1 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/framework.js +3 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/outbound.js +1 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f2d30cfc360482320a52a4fcde8a70f3569df79ab30be24650fda58eb60052cf/util.js +1 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/asset.f9b17c134d24cf60e1d26c033b5f4f247b759149619ac0aac341b950a10ccf14/index.js +72 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/integ.json +27 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/manifest.json +742 -0
- package/integ-tests/integ.rootmail-custom-santa.ts.snapshot/tree.json +5893 -0
- package/integ-tests/integ.rootmail.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.assets.json +2 -2
- package/integ-tests/integ.rootmail.ts.snapshot/SetupTestIntegStackDefaultTestDeployAssert6EB6FF77.template.json +3 -3
- package/integ-tests/integ.rootmail.ts.snapshot/manifest.json +1 -1
- package/lib/index-cli-synth.js +22 -11
- package/lib/index.js +2 -1
- package/lib/rootmail.d.ts +5 -1
- package/lib/rootmail.js +3 -2
- package/lib/scripts/publish-assets.js +18 -22
- package/lib/ses-receive.d.ts +5 -1
- package/lib/ses-receive.js +36 -14
- package/package.json +11 -6
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface LogRetentionEvent extends Omit<AWSLambda.CloudFormationCustomResourceEvent, 'ResourceProperties'> {
|
|
2
|
+
ResourceProperties: {
|
|
3
|
+
ServiceToken: string;
|
|
4
|
+
LogGroupName: string;
|
|
5
|
+
LogGroupRegion?: string;
|
|
6
|
+
RetentionInDays?: string;
|
|
7
|
+
SdkRetry?: {
|
|
8
|
+
maxRetries?: string;
|
|
9
|
+
};
|
|
10
|
+
RemovalPolicy?: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare function handler(event: LogRetentionEvent, context: AWSLambda.Context): Promise<void>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.handler=void 0;const Logs=require("@aws-sdk/client-cloudwatch-logs");async function createLogGroupSafe(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.CreateLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceAlreadyExistsException||error.name==="ResourceAlreadyExistsException")return;throw error}})}async function deleteLogGroup(logGroupName,client,withDelay){await withDelay(async()=>{try{const params={logGroupName},command=new Logs.DeleteLogGroupCommand(params);await client.send(command)}catch(error){if(error instanceof Logs.ResourceNotFoundException||error.name==="ResourceNotFoundException")return;throw error}})}async function setRetentionPolicy(logGroupName,client,withDelay,retentionInDays){await withDelay(async()=>{if(retentionInDays){const params={logGroupName,retentionInDays},putCommand=new Logs.PutRetentionPolicyCommand(params);await client.send(putCommand)}else{const params={logGroupName},deleteCommand=new Logs.DeleteRetentionPolicyCommand(params);await client.send(deleteCommand)}})}async function handler(event,context){try{console.log(JSON.stringify({...event,ResponseURL:"..."}));const logGroupName=event.ResourceProperties.LogGroupName,logGroupRegion=event.ResourceProperties.LogGroupRegion,withDelay=makeWithDelay(parseIntOptional(event.ResourceProperties.SdkRetry?.maxRetries)),sdkConfig={logger:console,region:logGroupRegion},client=new Logs.CloudWatchLogsClient(sdkConfig);if((event.RequestType==="Create"||event.RequestType==="Update")&&(await createLogGroupSafe(logGroupName,client,withDelay),await setRetentionPolicy(logGroupName,client,withDelay,parseIntOptional(event.ResourceProperties.RetentionInDays)),event.RequestType==="Create")){const clientForCustomResourceFunction=new Logs.CloudWatchLogsClient({logger:console,region:process.env.AWS_REGION});await createLogGroupSafe(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay),await setRetentionPolicy(`/aws/lambda/${context.functionName}`,clientForCustomResourceFunction,withDelay,1)}event.RequestType==="Delete"&&event.ResourceProperties.RemovalPolicy==="destroy"&&await deleteLogGroup(logGroupName,client,withDelay),await respond("SUCCESS","OK",logGroupName)}catch(e){console.log(e),await respond("FAILED",e.message,event.ResourceProperties.LogGroupName)}function respond(responseStatus,reason,physicalResourceId){const responseBody=JSON.stringify({Status:responseStatus,Reason:reason,PhysicalResourceId:physicalResourceId,StackId:event.StackId,RequestId:event.RequestId,LogicalResourceId:event.LogicalResourceId,Data:{LogGroupName:event.ResourceProperties.LogGroupName}});console.log("Responding",responseBody);const parsedUrl=require("url").parse(event.ResponseURL),requestOptions={hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}};return new Promise((resolve,reject)=>{try{const request=require("https").request(requestOptions,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}}exports.handler=handler;function parseIntOptional(value,base=10){if(value!==void 0)return parseInt(value,base)}function makeWithDelay(maxRetries=5,delayBase=100,delayCap=10*1e3){return async block=>{let attempts=0;do try{return await block()}catch(error){if(error instanceof Logs.OperationAbortedException||error.name==="OperationAbortedException")if(attempts<maxRetries){attempts++,await new Promise(resolve=>setTimeout(resolve,calculateDelay(attempts,delayBase,delayCap)));continue}else throw new Error("Out of attempts to change log group");throw error}while(!0)}}function calculateDelay(attempt,base,cap){return Math.round(Math.random()*Math.min(cap,base*2**attempt))}
|
|
@@ -0,0 +1,61 @@
|
|
|
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-receipt-ruleset-activation.is-complete-handler.ts
|
|
21
|
+
var ses_receipt_ruleset_activation_is_complete_handler_exports = {};
|
|
22
|
+
__export(ses_receipt_ruleset_activation_is_complete_handler_exports, {
|
|
23
|
+
PROP_EMAILBUCKET_NAME: () => PROP_EMAILBUCKET_NAME,
|
|
24
|
+
handler: () => handler
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(ses_receipt_ruleset_activation_is_complete_handler_exports);
|
|
27
|
+
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
28
|
+
var PROP_EMAILBUCKET_NAME = "EmailBucketName";
|
|
29
|
+
var fileKey = "RootMail/AMAZON_SES_SETUP_NOTIFICATION";
|
|
30
|
+
var s3 = new import_client_s3.S3();
|
|
31
|
+
async function handler(event) {
|
|
32
|
+
const emailBucketName = event.ResourceProperties[PROP_EMAILBUCKET_NAME];
|
|
33
|
+
switch (event.RequestType) {
|
|
34
|
+
case "Create":
|
|
35
|
+
console.log(`Testing if '${fileKey}' file is present in the S3 bucket: ${emailBucketName}`);
|
|
36
|
+
const result = await s3.headObject({
|
|
37
|
+
Bucket: emailBucketName,
|
|
38
|
+
Key: fileKey
|
|
39
|
+
});
|
|
40
|
+
if (result.$metadata.httpStatusCode === 404) {
|
|
41
|
+
console.log(`File ${fileKey} NOT found. IsComplete: false`);
|
|
42
|
+
return {
|
|
43
|
+
IsComplete: false
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
console.log(`File ${fileKey} found. SES setup complete. Proceeding`);
|
|
47
|
+
return {
|
|
48
|
+
IsComplete: true
|
|
49
|
+
};
|
|
50
|
+
case "Update":
|
|
51
|
+
case "Delete":
|
|
52
|
+
return {
|
|
53
|
+
IsComplete: true
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
58
|
+
0 && (module.exports = {
|
|
59
|
+
PROP_EMAILBUCKET_NAME,
|
|
60
|
+
handler
|
|
61
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
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/hosted-zone-dkim-propagation.is-complete-handler.ts
|
|
21
|
+
var hosted_zone_dkim_propagation_is_complete_handler_exports = {};
|
|
22
|
+
__export(hosted_zone_dkim_propagation_is_complete_handler_exports, {
|
|
23
|
+
PROP_DOMAIN: () => PROP_DOMAIN,
|
|
24
|
+
handler: () => handler
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(hosted_zone_dkim_propagation_is_complete_handler_exports);
|
|
27
|
+
var import_client_ses = require("@aws-sdk/client-ses");
|
|
28
|
+
var PROP_DOMAIN = "Domain";
|
|
29
|
+
var ses = new import_client_ses.SES();
|
|
30
|
+
async function handler(event) {
|
|
31
|
+
const domain = event.ResourceProperties[PROP_DOMAIN];
|
|
32
|
+
switch (event.RequestType) {
|
|
33
|
+
case "Create":
|
|
34
|
+
const isReady = await internalHandler(domain);
|
|
35
|
+
return { IsComplete: isReady };
|
|
36
|
+
case "Update":
|
|
37
|
+
case "Delete":
|
|
38
|
+
return {
|
|
39
|
+
IsComplete: true
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function log(msg) {
|
|
44
|
+
console.log(JSON.stringify(msg));
|
|
45
|
+
}
|
|
46
|
+
async function internalHandler(domain) {
|
|
47
|
+
log({
|
|
48
|
+
domain,
|
|
49
|
+
level: "debug"
|
|
50
|
+
});
|
|
51
|
+
const sendingResponse = await ses.getAccountSendingEnabled({});
|
|
52
|
+
if (!sendingResponse.Enabled) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
log("sending enabled");
|
|
56
|
+
const identityVerificationResponse = await ses.getIdentityVerificationAttributes({ Identities: [domain] });
|
|
57
|
+
const identityVerificationStatus = identityVerificationResponse.VerificationAttributes[domain].VerificationStatus;
|
|
58
|
+
if (identityVerificationStatus !== "Success") {
|
|
59
|
+
log(`Identity Verification status not successful. Was '${identityVerificationStatus}'`);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
log("identitity verification successful");
|
|
63
|
+
const identityDkimRes = await ses.getIdentityDkimAttributes({ Identities: [domain] });
|
|
64
|
+
const identityDkimStatus = identityDkimRes.DkimAttributes[domain].DkimVerificationStatus;
|
|
65
|
+
if (identityDkimStatus !== "Success") {
|
|
66
|
+
log(`DKIM status not successful. Was '${identityDkimStatus}'`);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
log("DKIM verification successful");
|
|
70
|
+
const identityNotificationRes = await ses.getIdentityNotificationAttributes({ Identities: [domain] });
|
|
71
|
+
const forwardingEnabled = identityNotificationRes.NotificationAttributes[domain].ForwardingEnabled;
|
|
72
|
+
if (!forwardingEnabled) {
|
|
73
|
+
log(`Forwarding not enabled. Was '${forwardingEnabled}'`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
log("forwarding enabled");
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
+
0 && (module.exports = {
|
|
81
|
+
PROP_DOMAIN,
|
|
82
|
+
handler
|
|
83
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
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/hosted-zone-dkim-propagation.on-event-handler.ts
|
|
21
|
+
var hosted_zone_dkim_propagation_on_event_handler_exports = {};
|
|
22
|
+
__export(hosted_zone_dkim_propagation_on_event_handler_exports, {
|
|
23
|
+
PROP_DOMAIN: () => PROP_DOMAIN,
|
|
24
|
+
handler: () => handler
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(hosted_zone_dkim_propagation_on_event_handler_exports);
|
|
27
|
+
var PROP_DOMAIN = "Domain";
|
|
28
|
+
async function handler(event) {
|
|
29
|
+
switch (event.RequestType) {
|
|
30
|
+
case "Create":
|
|
31
|
+
console.log(`${event.RequestType} DKIM propagation. PhysicalResourceId: ${event.RequestId}`);
|
|
32
|
+
return {
|
|
33
|
+
PhysicalResourceId: event.RequestId
|
|
34
|
+
};
|
|
35
|
+
case "Update":
|
|
36
|
+
case "Delete":
|
|
37
|
+
console.log(`${event.RequestType} DKIM propagation, doing nothing. PhysicalResourceId: ${event.PhysicalResourceId}`);
|
|
38
|
+
return {
|
|
39
|
+
PhysicalResourceId: event.PhysicalResourceId
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
PROP_DOMAIN,
|
|
46
|
+
handler
|
|
47
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
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-receipt-ruleset-activation.on-event-handler.ts
|
|
21
|
+
var ses_receipt_ruleset_activation_on_event_handler_exports = {};
|
|
22
|
+
__export(ses_receipt_ruleset_activation_on_event_handler_exports, {
|
|
23
|
+
PROP_DOMAIN: () => PROP_DOMAIN,
|
|
24
|
+
PROP_EMAILBUCKET_NAME: () => PROP_EMAILBUCKET_NAME,
|
|
25
|
+
PROP_OPS_SANTA_FUNCTION_ARN: () => PROP_OPS_SANTA_FUNCTION_ARN,
|
|
26
|
+
PROP_RULESET_SETTLE_TIME_SECONDS: () => PROP_RULESET_SETTLE_TIME_SECONDS,
|
|
27
|
+
PROP_SUBDOMAIN: () => PROP_SUBDOMAIN,
|
|
28
|
+
handler: () => handler
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(ses_receipt_ruleset_activation_on_event_handler_exports);
|
|
31
|
+
var import_client_ses = require("@aws-sdk/client-ses");
|
|
32
|
+
var PROP_DOMAIN = "Domain";
|
|
33
|
+
var PROP_SUBDOMAIN = "Subdomain";
|
|
34
|
+
var PROP_EMAILBUCKET_NAME = "EmailBucketName";
|
|
35
|
+
var PROP_OPS_SANTA_FUNCTION_ARN = "OpsSantaFunctionArn";
|
|
36
|
+
var PROP_RULESET_SETTLE_TIME_SECONDS = "RulesetSettleTimeSeconds";
|
|
37
|
+
var ses = new import_client_ses.SES();
|
|
38
|
+
async function handler(event) {
|
|
39
|
+
const domain = event.ResourceProperties[PROP_DOMAIN];
|
|
40
|
+
const subdomain = event.ResourceProperties[PROP_SUBDOMAIN];
|
|
41
|
+
const emailBucketName = event.ResourceProperties[PROP_EMAILBUCKET_NAME];
|
|
42
|
+
const opsSantaFunctionArn = event.ResourceProperties[PROP_OPS_SANTA_FUNCTION_ARN];
|
|
43
|
+
const logicalResourceId = event.LogicalResourceId;
|
|
44
|
+
const ruleSetName = "RootMail";
|
|
45
|
+
const ruleName = "Receive";
|
|
46
|
+
const rootmailBucketObjectKeyPrefix = "RootMail";
|
|
47
|
+
switch (event.RequestType) {
|
|
48
|
+
case "Create":
|
|
49
|
+
console.log(`${event.RequestType} SES ReceiptRuleSet. PhysicalResourceId: ${event.RequestId}`);
|
|
50
|
+
await ses.createReceiptRuleSet({ RuleSetName: ruleSetName });
|
|
51
|
+
await ses.createReceiptRule({
|
|
52
|
+
RuleSetName: ruleSetName,
|
|
53
|
+
Rule: {
|
|
54
|
+
Name: ruleName,
|
|
55
|
+
Enabled: true,
|
|
56
|
+
TlsPolicy: "Require",
|
|
57
|
+
ScanEnabled: true,
|
|
58
|
+
Recipients: [`root@${subdomain}.${domain}`],
|
|
59
|
+
Actions: [
|
|
60
|
+
{
|
|
61
|
+
S3Action: {
|
|
62
|
+
BucketName: emailBucketName,
|
|
63
|
+
ObjectKeyPrefix: rootmailBucketObjectKeyPrefix
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
LambdaAction: {
|
|
68
|
+
FunctionArn: opsSantaFunctionArn
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
console.log("Activating SES ReceiptRuleSet:", logicalResourceId);
|
|
75
|
+
await ses.setActiveReceiptRuleSet({ RuleSetName: ruleSetName });
|
|
76
|
+
return {
|
|
77
|
+
PhysicalResourceId: event.RequestId
|
|
78
|
+
};
|
|
79
|
+
case "Update":
|
|
80
|
+
console.log(`${event.RequestType} SES ReceiptRuleSet. PhysicalResourceId: ${event.PhysicalResourceId}`);
|
|
81
|
+
return {
|
|
82
|
+
PhysicalResourceId: event.PhysicalResourceId
|
|
83
|
+
};
|
|
84
|
+
case "Delete":
|
|
85
|
+
console.log("Deactivating SES ReceiptRuleSet:", logicalResourceId);
|
|
86
|
+
await ses.setActiveReceiptRuleSet({ RuleSetName: void 0 });
|
|
87
|
+
await ses.deleteReceiptRule({
|
|
88
|
+
RuleName: ruleName,
|
|
89
|
+
RuleSetName: ruleSetName
|
|
90
|
+
});
|
|
91
|
+
await ses.deleteReceiptRuleSet({ RuleSetName: ruleSetName });
|
|
92
|
+
return {
|
|
93
|
+
PhysicalResourceId: event.PhysicalResourceId
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
98
|
+
0 && (module.exports = {
|
|
99
|
+
PROP_DOMAIN,
|
|
100
|
+
PROP_EMAILBUCKET_NAME,
|
|
101
|
+
PROP_OPS_SANTA_FUNCTION_ARN,
|
|
102
|
+
PROP_RULESET_SETTLE_TIME_SECONDS,
|
|
103
|
+
PROP_SUBDOMAIN,
|
|
104
|
+
handler
|
|
105
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
// integ-tests/functions/send-email-handler.ts
|
|
21
|
+
var send_email_handler_exports = {};
|
|
22
|
+
__export(send_email_handler_exports, {
|
|
23
|
+
handler: () => handler
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(send_email_handler_exports);
|
|
26
|
+
var import_client_ses = require("@aws-sdk/client-ses");
|
|
27
|
+
var ses = new import_client_ses.SES();
|
|
28
|
+
var handler = async (event) => {
|
|
29
|
+
const id = event.id || "test-id-1";
|
|
30
|
+
const text = event.text || "test";
|
|
31
|
+
const sourceMail = event.sourceMail || "test@example.com";
|
|
32
|
+
const toMail = event.toMail || "root@example.com";
|
|
33
|
+
const ruleAfter = await ses.describeReceiptRule({
|
|
34
|
+
RuleSetName: "RootMail",
|
|
35
|
+
RuleName: "Receive"
|
|
36
|
+
});
|
|
37
|
+
log({ message: "Rule:", rule: ruleAfter.Rule });
|
|
38
|
+
const params = {
|
|
39
|
+
Source: sourceMail,
|
|
40
|
+
Destination: {
|
|
41
|
+
ToAddresses: [toMail]
|
|
42
|
+
},
|
|
43
|
+
Message: {
|
|
44
|
+
Subject: {
|
|
45
|
+
Data: id
|
|
46
|
+
},
|
|
47
|
+
Body: {
|
|
48
|
+
Text: {
|
|
49
|
+
Data: text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
try {
|
|
55
|
+
const res = await ses.sendEmail(params);
|
|
56
|
+
if (res.$metadata.httpStatusCode !== 200) {
|
|
57
|
+
log({
|
|
58
|
+
message: "Error sending email",
|
|
59
|
+
params,
|
|
60
|
+
messageId: res.MessageId,
|
|
61
|
+
err: `httpStatusCode: ${res.$metadata.httpStatusCode}`
|
|
62
|
+
});
|
|
63
|
+
return { sendStatusCode: 500, err: res.$metadata.httpStatusCode };
|
|
64
|
+
}
|
|
65
|
+
log({
|
|
66
|
+
message: "Email sent",
|
|
67
|
+
params,
|
|
68
|
+
res
|
|
69
|
+
});
|
|
70
|
+
return { sendStatusCode: 200 };
|
|
71
|
+
} catch (err) {
|
|
72
|
+
log({
|
|
73
|
+
message: "Error (catch) sending email",
|
|
74
|
+
err
|
|
75
|
+
});
|
|
76
|
+
return { sendStatusCode: 500, err };
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
function log(msg) {
|
|
80
|
+
console.log(JSON.stringify(msg));
|
|
81
|
+
}
|
|
82
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
83
|
+
0 && (module.exports = {
|
|
84
|
+
handler
|
|
85
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Retry=exports.safeHandler=exports.includeStackTraces=exports.submitResponse=exports.MISSING_PHYSICAL_ID_MARKER=exports.CREATE_FAILED_PHYSICAL_ID_MARKER=void 0;const url=require("url"),outbound_1=require("./outbound"),util_1=require("./util");exports.CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",exports.MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function submitResponse(status,event,options={}){const json={Status:status,Reason:options.reason||status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||exports.MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:options.noEcho,Data:event.Data};(0,util_1.log)("submit response to cloudformation",json);const responseBody=JSON.stringify(json),parsedUrl=url.parse(event.ResponseURL),retryOptions={attempts:5,sleep:1e3};await(0,util_1.withRetries)(retryOptions,outbound_1.httpRequest)({hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}},responseBody)}exports.submitResponse=submitResponse,exports.includeStackTraces=!0;function safeHandler(block){return async event=>{if(event.RequestType==="Delete"&&event.PhysicalResourceId===exports.CREATE_FAILED_PHYSICAL_ID_MARKER){(0,util_1.log)("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{await block(event)}catch(e){if(e instanceof Retry)throw(0,util_1.log)("retry requested by handler"),e;event.PhysicalResourceId||(event.RequestType==="Create"?((0,util_1.log)("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),event.PhysicalResourceId=exports.CREATE_FAILED_PHYSICAL_ID_MARKER):(0,util_1.log)(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({...event,ResponseURL:"..."})}`)),await submitResponse("FAILED",event,{reason:exports.includeStackTraces?e.stack:e.message})}}}exports.safeHandler=safeHandler;class Retry extends Error{}exports.Retry=Retry;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME=exports.FRAMEWORK_IS_COMPLETE_HANDLER_NAME=exports.FRAMEWORK_ON_EVENT_HANDLER_NAME=exports.WAITER_STATE_MACHINE_ARN_ENV=exports.USER_IS_COMPLETE_FUNCTION_ARN_ENV=exports.USER_ON_EVENT_FUNCTION_ARN_ENV=void 0,exports.USER_ON_EVENT_FUNCTION_ARN_ENV="USER_ON_EVENT_FUNCTION_ARN",exports.USER_IS_COMPLETE_FUNCTION_ARN_ENV="USER_IS_COMPLETE_FUNCTION_ARN",exports.WAITER_STATE_MACHINE_ARN_ENV="WAITER_STATE_MACHINE_ARN",exports.FRAMEWORK_ON_EVENT_HANDLER_NAME="onEvent",exports.FRAMEWORK_IS_COMPLETE_HANDLER_NAME="isComplete",exports.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME="onTimeout";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";const cfnResponse=require("./cfn-response"),consts=require("./consts"),outbound_1=require("./outbound"),util_1=require("./util");async function onEvent(cfnRequest){const sanitizedRequest={...cfnRequest,ResponseURL:"..."};(0,util_1.log)("onEventHandler",sanitizedRequest),cfnRequest.ResourceProperties=cfnRequest.ResourceProperties||{};const onEventResult=await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV,sanitizedRequest,cfnRequest.ResponseURL);(0,util_1.log)("onEvent returned:",onEventResult);const resourceEvent=createResponseEvent(cfnRequest,onEventResult);if((0,util_1.log)("event:",onEventResult),!process.env[consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV])return cfnResponse.submitResponse("SUCCESS",resourceEvent,{noEcho:resourceEvent.NoEcho});const waiter={stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV),name:resourceEvent.RequestId,input:JSON.stringify(resourceEvent)};(0,util_1.log)("starting waiter",waiter),await(0,outbound_1.startExecution)(waiter)}async function isComplete(event){const sanitizedRequest={...event,ResponseURL:"..."};(0,util_1.log)("isComplete",sanitizedRequest);const isCompleteResult=await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV,sanitizedRequest,event.ResponseURL);if((0,util_1.log)("user isComplete returned:",isCompleteResult),!isCompleteResult.IsComplete)throw isCompleteResult.Data&&Object.keys(isCompleteResult.Data).length>0?new Error('"Data" is not allowed if "IsComplete" is "False"'):new cfnResponse.Retry(JSON.stringify(event));const response={...event,...isCompleteResult,Data:{...event.Data,...isCompleteResult.Data}};await cfnResponse.submitResponse("SUCCESS",response,{noEcho:event.NoEcho})}async function onTimeout(timeoutEvent){(0,util_1.log)("timeoutHandler",timeoutEvent);const isCompleteRequest=JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage);await cfnResponse.submitResponse("FAILED",isCompleteRequest,{reason:"Operation timed out"})}async function invokeUserFunction(functionArnEnv,sanitizedPayload,responseUrl){const functionArn=(0,util_1.getEnv)(functionArnEnv);(0,util_1.log)(`executing user function ${functionArn} with payload`,sanitizedPayload);const resp=await(0,outbound_1.invokeFunction)({FunctionName:functionArn,Payload:JSON.stringify({...sanitizedPayload,ResponseURL:responseUrl})});(0,util_1.log)("user function response:",resp,typeof resp);const jsonPayload=parseJsonPayload(resp.Payload);if(resp.FunctionError){(0,util_1.log)("user function threw an error:",resp.FunctionError);const errorMessage=jsonPayload.errorMessage||"error",arn=functionArn.split(":"),functionName=arn[arn.length-1],message=[errorMessage,"",`Logs: /aws/lambda/${functionName}`,""].join(`
|
|
2
|
+
`),e=new Error(message);throw jsonPayload.trace&&(e.stack=[message,...jsonPayload.trace.slice(1)].join(`
|
|
3
|
+
`)),e}return jsonPayload}function parseJsonPayload(payload){if(!payload)return{};let text=new TextDecoder().decode(Buffer.from(payload));try{return JSON.parse(text)}catch{throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`)}}function createResponseEvent(cfnRequest,onEventResult){onEventResult=onEventResult||{};const physicalResourceId=onEventResult.PhysicalResourceId||defaultPhysicalResourceId(cfnRequest);if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}" during deletion`);return cfnRequest.RequestType==="Update"&&physicalResourceId!==cfnRequest.PhysicalResourceId&&(0,util_1.log)(`UPDATE: changing physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}"`),{...cfnRequest,...onEventResult,PhysicalResourceId:physicalResourceId}}function defaultPhysicalResourceId(req){switch(req.RequestType){case"Create":return req.RequestId;case"Update":case"Delete":return req.PhysicalResourceId;default:throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`)}}module.exports={[consts.FRAMEWORK_ON_EVENT_HANDLER_NAME]:cfnResponse.safeHandler(onEvent),[consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME]:cfnResponse.safeHandler(isComplete),[consts.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME]:onTimeout};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.httpRequest=exports.invokeFunction=exports.startExecution=void 0;const https=require("https"),client_lambda_1=require("@aws-sdk/client-lambda"),client_sfn_1=require("@aws-sdk/client-sfn"),FRAMEWORK_HANDLER_TIMEOUT=9e5,awsSdkConfig={httpOptions:{timeout:FRAMEWORK_HANDLER_TIMEOUT}};async function defaultHttpRequest(options,responseBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,resolve);request.on("error",reject),request.write(responseBody),request.end()}catch(e){reject(e)}})}let sfn,lambda;async function defaultStartExecution(req){return sfn||(sfn=new client_sfn_1.SFN(awsSdkConfig)),sfn.startExecution(req)}async function defaultInvokeFunction(req){lambda||(lambda=new client_lambda_1.Lambda(awsSdkConfig));try{return await lambda.invoke(req)}catch{return await(0,client_lambda_1.waitUntilFunctionActive)({client:lambda,maxWaitTime:60},{FunctionName:req.FunctionName}),await lambda.invoke(req)}}exports.startExecution=defaultStartExecution,exports.invokeFunction=defaultInvokeFunction,exports.httpRequest=defaultHttpRequest;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withRetries=exports.log=exports.getEnv=void 0;function getEnv(name){const value=process.env[name];if(!value)throw new Error(`The environment variable "${name}" is not defined`);return value}exports.getEnv=getEnv;function log(title,...args){console.log("[provider-framework]",title,...args.map(x=>typeof x=="object"?JSON.stringify(x,void 0,2):x))}exports.log=log;function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}exports.withRetries=withRetries;async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}
|
|
@@ -0,0 +1,72 @@
|
|
|
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/hosted-zone-dkim-verification-records.on-event-handler.ts
|
|
21
|
+
var hosted_zone_dkim_verification_records_on_event_handler_exports = {};
|
|
22
|
+
__export(hosted_zone_dkim_verification_records_on_event_handler_exports, {
|
|
23
|
+
ATTR_DKIM_TOKENS: () => ATTR_DKIM_TOKENS,
|
|
24
|
+
ATTR_VERIFICATION_TOKEN: () => ATTR_VERIFICATION_TOKEN,
|
|
25
|
+
PROP_DOMAIN: () => PROP_DOMAIN,
|
|
26
|
+
handler: () => handler
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(hosted_zone_dkim_verification_records_on_event_handler_exports);
|
|
29
|
+
var import_client_ses = require("@aws-sdk/client-ses");
|
|
30
|
+
var PROP_DOMAIN = "Domain";
|
|
31
|
+
var ATTR_VERIFICATION_TOKEN = "VerificationToken";
|
|
32
|
+
var ATTR_DKIM_TOKENS = "DkimTokens";
|
|
33
|
+
var ses = new import_client_ses.SES();
|
|
34
|
+
async function handler(event) {
|
|
35
|
+
const domain = event.ResourceProperties[PROP_DOMAIN];
|
|
36
|
+
switch (event.RequestType) {
|
|
37
|
+
case "Create":
|
|
38
|
+
case "Update":
|
|
39
|
+
let physicalResourceId = event.PhysicalResourceId;
|
|
40
|
+
if (event.RequestType === "Create") {
|
|
41
|
+
physicalResourceId = event.RequestId;
|
|
42
|
+
}
|
|
43
|
+
console.log(`${event.RequestType}: Do Domain verification and DKIM records for ${event.LogicalResourceId} and domain '${domain}' with PhysicalResourceId '${physicalResourceId}'`);
|
|
44
|
+
const verifyDomainResponse = await ses.verifyDomainIdentity({ Domain: domain });
|
|
45
|
+
const verificationToken = verifyDomainResponse.VerificationToken;
|
|
46
|
+
console.log(`${event.RequestType}: Got verification token '${verificationToken}' for domain '${domain}'`);
|
|
47
|
+
const verifyDomainDkimResponse = await ses.verifyDomainDkim({ Domain: domain });
|
|
48
|
+
const dkimTokens = verifyDomainDkimResponse.DkimTokens;
|
|
49
|
+
console.log(`${event.RequestType}: Got DKIM tokens '${dkimTokens}' for domain '${domain}'`);
|
|
50
|
+
return {
|
|
51
|
+
PhysicalResourceId: physicalResourceId,
|
|
52
|
+
Data: {
|
|
53
|
+
[ATTR_VERIFICATION_TOKEN]: verificationToken,
|
|
54
|
+
[ATTR_DKIM_TOKENS]: dkimTokens
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
case "Delete":
|
|
58
|
+
console.log(`Deleting Domain identity for domain '${domain}' with PhysicalResourceId '${event.PhysicalResourceId}'`);
|
|
59
|
+
const deleteResponse = await ses.deleteIdentity({ Identity: domain });
|
|
60
|
+
console.log(`Deleted Domain identity for domain '${domain}'`, deleteResponse);
|
|
61
|
+
return {
|
|
62
|
+
PhysicalResourceId: event.PhysicalResourceId
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
67
|
+
0 && (module.exports = {
|
|
68
|
+
ATTR_DKIM_TOKENS,
|
|
69
|
+
ATTR_VERIFICATION_TOKEN,
|
|
70
|
+
PROP_DOMAIN,
|
|
71
|
+
handler
|
|
72
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "33.0.0",
|
|
3
|
+
"testCases": {
|
|
4
|
+
"SetupTestIntegStack/DefaultTest": {
|
|
5
|
+
"stacks": [
|
|
6
|
+
"RootmailIntegTestStack"
|
|
7
|
+
],
|
|
8
|
+
"hooks": {
|
|
9
|
+
"postDestroy": [
|
|
10
|
+
"echo \"Post hook\""
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"regions": [
|
|
14
|
+
"${Token[AWS.Region.12]}"
|
|
15
|
+
],
|
|
16
|
+
"cdkCommandOptions": {
|
|
17
|
+
"destroy": {
|
|
18
|
+
"args": {
|
|
19
|
+
"force": true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"assertionStack": "SetupTestIntegStack/DefaultTest/DeployAssert",
|
|
24
|
+
"assertionStackName": "SetupTestIntegStackDefaultTestDeployAssert6EB6FF77"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|