@wraps.dev/cli 2.11.7 → 2.11.8
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/dist/cli.js
CHANGED
|
@@ -825,8 +825,8 @@ async function isAWSCLIInstalled() {
|
|
|
825
825
|
}
|
|
826
826
|
async function getAWSCLIVersion() {
|
|
827
827
|
try {
|
|
828
|
-
const
|
|
829
|
-
const match =
|
|
828
|
+
const output3 = execSync("aws --version", { encoding: "utf-8" });
|
|
829
|
+
const match = output3.match(/aws-cli\/(\d+\.\d+\.\d+)/);
|
|
830
830
|
return match ? match[1] : null;
|
|
831
831
|
} catch {
|
|
832
832
|
return null;
|
|
@@ -4467,10 +4467,10 @@ var init_metadata = __esm({
|
|
|
4467
4467
|
async function roleExists(roleName) {
|
|
4468
4468
|
try {
|
|
4469
4469
|
const { IAMClient: IAMClient4, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
|
|
4470
|
-
const
|
|
4470
|
+
const iam9 = new IAMClient4({
|
|
4471
4471
|
region: process.env.AWS_REGION || "us-east-1"
|
|
4472
4472
|
});
|
|
4473
|
-
await
|
|
4473
|
+
await iam9.send(new GetRoleCommand3({ RoleName: roleName }));
|
|
4474
4474
|
return true;
|
|
4475
4475
|
} catch (error) {
|
|
4476
4476
|
if (error instanceof Error && (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity")) {
|
|
@@ -4760,7 +4760,7 @@ import { builtinModules } from "module";
|
|
|
4760
4760
|
import { tmpdir } from "os";
|
|
4761
4761
|
import { dirname as dirname2, join as join7 } from "path";
|
|
4762
4762
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4763
|
-
import * as
|
|
4763
|
+
import * as aws7 from "@pulumi/aws";
|
|
4764
4764
|
import * as pulumi11 from "@pulumi/pulumi";
|
|
4765
4765
|
import { build } from "esbuild";
|
|
4766
4766
|
function getPackageRoot() {
|
|
@@ -4835,7 +4835,7 @@ Try running: pnpm build`
|
|
|
4835
4835
|
}
|
|
4836
4836
|
async function deployLambdaFunctions(config2) {
|
|
4837
4837
|
const eventProcessorCode = await getLambdaCode("event-processor");
|
|
4838
|
-
const lambdaRole = new
|
|
4838
|
+
const lambdaRole = new aws7.iam.Role("wraps-email-lambda-role", {
|
|
4839
4839
|
assumeRolePolicy: JSON.stringify({
|
|
4840
4840
|
Version: "2012-10-17",
|
|
4841
4841
|
Statement: [
|
|
@@ -4850,11 +4850,11 @@ async function deployLambdaFunctions(config2) {
|
|
|
4850
4850
|
ManagedBy: "wraps-cli"
|
|
4851
4851
|
}
|
|
4852
4852
|
});
|
|
4853
|
-
new
|
|
4853
|
+
new aws7.iam.RolePolicyAttachment("wraps-email-lambda-basic-execution", {
|
|
4854
4854
|
role: lambdaRole.name,
|
|
4855
4855
|
policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
4856
4856
|
});
|
|
4857
|
-
new
|
|
4857
|
+
new aws7.iam.RolePolicy("wraps-email-lambda-policy", {
|
|
4858
4858
|
role: lambdaRole.name,
|
|
4859
4859
|
policy: pulumi11.all([config2.tableName, config2.queueArn]).apply(
|
|
4860
4860
|
([tableName, queueArn]) => JSON.stringify({
|
|
@@ -4898,7 +4898,7 @@ async function deployLambdaFunctions(config2) {
|
|
|
4898
4898
|
RETENTION_DAYS: config2.retentionDays.toString()
|
|
4899
4899
|
}
|
|
4900
4900
|
};
|
|
4901
|
-
const eventProcessor = exists ? new
|
|
4901
|
+
const eventProcessor = exists ? new aws7.lambda.Function(
|
|
4902
4902
|
functionName,
|
|
4903
4903
|
{
|
|
4904
4904
|
name: functionName,
|
|
@@ -4919,7 +4919,7 @@ async function deployLambdaFunctions(config2) {
|
|
|
4919
4919
|
import: functionName
|
|
4920
4920
|
// Import existing function
|
|
4921
4921
|
}
|
|
4922
|
-
) : new
|
|
4922
|
+
) : new aws7.lambda.Function(functionName, {
|
|
4923
4923
|
name: functionName,
|
|
4924
4924
|
runtime: "nodejs24.x",
|
|
4925
4925
|
handler: "index.handler",
|
|
@@ -4949,14 +4949,14 @@ async function deployLambdaFunctions(config2) {
|
|
|
4949
4949
|
functionResponseTypes: ["ReportBatchItemFailures"]
|
|
4950
4950
|
// Enable partial batch responses
|
|
4951
4951
|
};
|
|
4952
|
-
const eventSourceMapping = existingMappingUuid ? new
|
|
4952
|
+
const eventSourceMapping = existingMappingUuid ? new aws7.lambda.EventSourceMapping(
|
|
4953
4953
|
"wraps-email-event-source-mapping",
|
|
4954
4954
|
mappingConfig,
|
|
4955
4955
|
{
|
|
4956
4956
|
import: existingMappingUuid
|
|
4957
4957
|
// Import with the UUID
|
|
4958
4958
|
}
|
|
4959
|
-
) : new
|
|
4959
|
+
) : new aws7.lambda.EventSourceMapping(
|
|
4960
4960
|
"wraps-email-event-source-mapping",
|
|
4961
4961
|
mappingConfig
|
|
4962
4962
|
);
|
|
@@ -4982,7 +4982,7 @@ __export(acm_exports, {
|
|
|
4982
4982
|
createACMCertificate: () => createACMCertificate
|
|
4983
4983
|
});
|
|
4984
4984
|
import { ACMClient as ACMClient2, DescribeCertificateCommand as DescribeCertificateCommand2 } from "@aws-sdk/client-acm";
|
|
4985
|
-
import * as
|
|
4985
|
+
import * as aws11 from "@pulumi/aws";
|
|
4986
4986
|
async function checkCertificateValidation(domain) {
|
|
4987
4987
|
try {
|
|
4988
4988
|
const acm3 = new ACMClient2({ region: "us-east-1" });
|
|
@@ -5009,10 +5009,10 @@ async function checkCertificateValidation(domain) {
|
|
|
5009
5009
|
}
|
|
5010
5010
|
}
|
|
5011
5011
|
async function createACMCertificate(config2) {
|
|
5012
|
-
const usEast1Provider = new
|
|
5012
|
+
const usEast1Provider = new aws11.Provider("acm-us-east-1", {
|
|
5013
5013
|
region: "us-east-1"
|
|
5014
5014
|
});
|
|
5015
|
-
const certificate = new
|
|
5015
|
+
const certificate = new aws11.acm.Certificate(
|
|
5016
5016
|
"wraps-email-tracking-cert",
|
|
5017
5017
|
{
|
|
5018
5018
|
domainName: config2.domain,
|
|
@@ -5035,7 +5035,7 @@ async function createACMCertificate(config2) {
|
|
|
5035
5035
|
);
|
|
5036
5036
|
let certificateValidation;
|
|
5037
5037
|
if (config2.hostedZoneId) {
|
|
5038
|
-
const validationRecord = new
|
|
5038
|
+
const validationRecord = new aws11.route53.Record(
|
|
5039
5039
|
"wraps-email-tracking-cert-validation",
|
|
5040
5040
|
{
|
|
5041
5041
|
zoneId: config2.hostedZoneId,
|
|
@@ -5045,7 +5045,7 @@ async function createACMCertificate(config2) {
|
|
|
5045
5045
|
ttl: 60
|
|
5046
5046
|
}
|
|
5047
5047
|
);
|
|
5048
|
-
certificateValidation = new
|
|
5048
|
+
certificateValidation = new aws11.acm.CertificateValidation(
|
|
5049
5049
|
"wraps-email-tracking-cert-validation-waiter",
|
|
5050
5050
|
{
|
|
5051
5051
|
certificateArn: certificate.arn,
|
|
@@ -5074,7 +5074,7 @@ var cloudfront_exports = {};
|
|
|
5074
5074
|
__export(cloudfront_exports, {
|
|
5075
5075
|
createCloudFrontTracking: () => createCloudFrontTracking
|
|
5076
5076
|
});
|
|
5077
|
-
import * as
|
|
5077
|
+
import * as aws12 from "@pulumi/aws";
|
|
5078
5078
|
async function findDistributionByAlias(alias) {
|
|
5079
5079
|
try {
|
|
5080
5080
|
const { CloudFrontClient, ListDistributionsCommand } = await import("@aws-sdk/client-cloudfront");
|
|
@@ -5090,10 +5090,10 @@ async function findDistributionByAlias(alias) {
|
|
|
5090
5090
|
}
|
|
5091
5091
|
}
|
|
5092
5092
|
async function createWAFWebACL() {
|
|
5093
|
-
const usEast1Provider = new
|
|
5093
|
+
const usEast1Provider = new aws12.Provider("waf-us-east-1", {
|
|
5094
5094
|
region: "us-east-1"
|
|
5095
5095
|
});
|
|
5096
|
-
const webAcl = new
|
|
5096
|
+
const webAcl = new aws12.wafv2.WebAcl(
|
|
5097
5097
|
"wraps-email-tracking-waf",
|
|
5098
5098
|
{
|
|
5099
5099
|
scope: "CLOUDFRONT",
|
|
@@ -5208,14 +5208,14 @@ async function createCloudFrontTracking(config2) {
|
|
|
5208
5208
|
Description: "Wraps email tracking CloudFront distribution"
|
|
5209
5209
|
}
|
|
5210
5210
|
};
|
|
5211
|
-
const distribution = existingDistributionId ? new
|
|
5211
|
+
const distribution = existingDistributionId ? new aws12.cloudfront.Distribution(
|
|
5212
5212
|
"wraps-email-tracking-cdn",
|
|
5213
5213
|
distributionConfig,
|
|
5214
5214
|
{
|
|
5215
5215
|
import: existingDistributionId
|
|
5216
5216
|
// Import existing distribution
|
|
5217
5217
|
}
|
|
5218
|
-
) : new
|
|
5218
|
+
) : new aws12.cloudfront.Distribution(
|
|
5219
5219
|
"wraps-email-tracking-cdn",
|
|
5220
5220
|
distributionConfig
|
|
5221
5221
|
);
|
|
@@ -5396,10 +5396,10 @@ var s3_inbound_exports = {};
|
|
|
5396
5396
|
__export(s3_inbound_exports, {
|
|
5397
5397
|
createS3InboundResources: () => createS3InboundResources
|
|
5398
5398
|
});
|
|
5399
|
-
import * as
|
|
5399
|
+
import * as aws13 from "@pulumi/aws";
|
|
5400
5400
|
async function createS3InboundResources(config2) {
|
|
5401
5401
|
const bucketName = `wraps-inbound-${config2.accountId}-${config2.region}`;
|
|
5402
|
-
const bucket = new
|
|
5402
|
+
const bucket = new aws13.s3.BucketV2("wraps-inbound-bucket", {
|
|
5403
5403
|
bucket: bucketName,
|
|
5404
5404
|
forceDestroy: true,
|
|
5405
5405
|
tags: {
|
|
@@ -5407,14 +5407,14 @@ async function createS3InboundResources(config2) {
|
|
|
5407
5407
|
Service: "email-inbound"
|
|
5408
5408
|
}
|
|
5409
5409
|
});
|
|
5410
|
-
new
|
|
5410
|
+
new aws13.s3.BucketPublicAccessBlock("wraps-inbound-public-access-block", {
|
|
5411
5411
|
bucket: bucket.id,
|
|
5412
5412
|
blockPublicAcls: true,
|
|
5413
5413
|
blockPublicPolicy: true,
|
|
5414
5414
|
ignorePublicAcls: true,
|
|
5415
5415
|
restrictPublicBuckets: true
|
|
5416
5416
|
});
|
|
5417
|
-
new
|
|
5417
|
+
new aws13.s3.BucketServerSideEncryptionConfigurationV2(
|
|
5418
5418
|
"wraps-inbound-encryption",
|
|
5419
5419
|
{
|
|
5420
5420
|
bucket: bucket.id,
|
|
@@ -5430,7 +5430,7 @@ async function createS3InboundResources(config2) {
|
|
|
5430
5430
|
if (config2.retention) {
|
|
5431
5431
|
const retentionDays = retentionToDays2(config2.retention);
|
|
5432
5432
|
if (retentionDays > 0) {
|
|
5433
|
-
new
|
|
5433
|
+
new aws13.s3.BucketLifecycleConfigurationV2("wraps-inbound-lifecycle", {
|
|
5434
5434
|
bucket: bucket.id,
|
|
5435
5435
|
rules: [
|
|
5436
5436
|
{
|
|
@@ -5444,8 +5444,8 @@ async function createS3InboundResources(config2) {
|
|
|
5444
5444
|
});
|
|
5445
5445
|
}
|
|
5446
5446
|
}
|
|
5447
|
-
const identity = await
|
|
5448
|
-
new
|
|
5447
|
+
const identity = await aws13.getCallerIdentity();
|
|
5448
|
+
new aws13.s3.BucketPolicy("wraps-inbound-bucket-policy", {
|
|
5449
5449
|
bucket: bucket.id,
|
|
5450
5450
|
policy: bucket.arn.apply(
|
|
5451
5451
|
(arn) => JSON.stringify({
|
|
@@ -5487,9 +5487,9 @@ var sqs_inbound_exports = {};
|
|
|
5487
5487
|
__export(sqs_inbound_exports, {
|
|
5488
5488
|
createSQSInboundResources: () => createSQSInboundResources
|
|
5489
5489
|
});
|
|
5490
|
-
import * as
|
|
5490
|
+
import * as aws14 from "@pulumi/aws";
|
|
5491
5491
|
function createSQSInboundResources() {
|
|
5492
|
-
const dlq = new
|
|
5492
|
+
const dlq = new aws14.sqs.Queue("wraps-inbound-events-dlq", {
|
|
5493
5493
|
name: "wraps-inbound-events-dlq",
|
|
5494
5494
|
messageRetentionSeconds: 1209600,
|
|
5495
5495
|
// 14 days
|
|
@@ -5499,7 +5499,7 @@ function createSQSInboundResources() {
|
|
|
5499
5499
|
Description: "Dead letter queue for failed inbound email processing"
|
|
5500
5500
|
}
|
|
5501
5501
|
});
|
|
5502
|
-
const queue = new
|
|
5502
|
+
const queue = new aws14.sqs.Queue("wraps-inbound-events", {
|
|
5503
5503
|
name: "wraps-inbound-events",
|
|
5504
5504
|
visibilityTimeoutSeconds: 300,
|
|
5505
5505
|
// Must be >= Lambda timeout (120s) * 2 + buffer
|
|
@@ -5536,11 +5536,11 @@ var lambda_inbound_exports = {};
|
|
|
5536
5536
|
__export(lambda_inbound_exports, {
|
|
5537
5537
|
deployInboundLambda: () => deployInboundLambda
|
|
5538
5538
|
});
|
|
5539
|
-
import * as
|
|
5539
|
+
import * as aws15 from "@pulumi/aws";
|
|
5540
5540
|
import * as pulumi12 from "@pulumi/pulumi";
|
|
5541
5541
|
async function deployInboundLambda(config2) {
|
|
5542
5542
|
const inboundProcessorCode = await getLambdaCode("inbound-processor");
|
|
5543
|
-
const lambdaRole = new
|
|
5543
|
+
const lambdaRole = new aws15.iam.Role("wraps-inbound-lambda-role", {
|
|
5544
5544
|
name: "wraps-inbound-lambda-role",
|
|
5545
5545
|
assumeRolePolicy: JSON.stringify({
|
|
5546
5546
|
Version: "2012-10-17",
|
|
@@ -5557,11 +5557,11 @@ async function deployInboundLambda(config2) {
|
|
|
5557
5557
|
Service: "email-inbound"
|
|
5558
5558
|
}
|
|
5559
5559
|
});
|
|
5560
|
-
new
|
|
5560
|
+
new aws15.iam.RolePolicyAttachment("wraps-inbound-lambda-basic-execution", {
|
|
5561
5561
|
role: lambdaRole.name,
|
|
5562
5562
|
policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
5563
5563
|
});
|
|
5564
|
-
new
|
|
5564
|
+
new aws15.iam.RolePolicy("wraps-inbound-lambda-policy", {
|
|
5565
5565
|
role: lambdaRole.name,
|
|
5566
5566
|
policy: pulumi12.all([config2.bucketArn, config2.dlqArn]).apply(
|
|
5567
5567
|
([bucketArn, dlqArn]) => JSON.stringify({
|
|
@@ -5590,7 +5590,7 @@ async function deployInboundLambda(config2) {
|
|
|
5590
5590
|
)
|
|
5591
5591
|
});
|
|
5592
5592
|
const functionName = "wraps-inbound-email-processor";
|
|
5593
|
-
const lambdaFunction = new
|
|
5593
|
+
const lambdaFunction = new aws15.lambda.Function(functionName, {
|
|
5594
5594
|
name: functionName,
|
|
5595
5595
|
runtime: "nodejs20.x",
|
|
5596
5596
|
handler: "index.handler",
|
|
@@ -5612,7 +5612,7 @@ async function deployInboundLambda(config2) {
|
|
|
5612
5612
|
Service: "email-inbound"
|
|
5613
5613
|
}
|
|
5614
5614
|
});
|
|
5615
|
-
const s3InvokePermission = new
|
|
5615
|
+
const s3InvokePermission = new aws15.lambda.Permission(
|
|
5616
5616
|
"wraps-inbound-s3-invoke",
|
|
5617
5617
|
{
|
|
5618
5618
|
action: "lambda:InvokeFunction",
|
|
@@ -5640,9 +5640,9 @@ var eventbridge_inbound_exports = {};
|
|
|
5640
5640
|
__export(eventbridge_inbound_exports, {
|
|
5641
5641
|
createEventBridgeInboundResources: () => createEventBridgeInboundResources
|
|
5642
5642
|
});
|
|
5643
|
-
import * as
|
|
5643
|
+
import * as aws16 from "@pulumi/aws";
|
|
5644
5644
|
function createEventBridgeInboundResources(config2) {
|
|
5645
|
-
const rule = new
|
|
5645
|
+
const rule = new aws16.cloudwatch.EventRule("wraps-inbound-events-rule", {
|
|
5646
5646
|
name: "wraps-inbound-events-to-webhook",
|
|
5647
5647
|
description: "Route inbound email events to webhook",
|
|
5648
5648
|
eventBusName: "default",
|
|
@@ -5659,7 +5659,7 @@ function createEventBridgeInboundResources(config2) {
|
|
|
5659
5659
|
let webhookApiDestination;
|
|
5660
5660
|
let webhookTarget;
|
|
5661
5661
|
if (config2.webhookUrl && config2.webhookSecret) {
|
|
5662
|
-
webhookConnection = new
|
|
5662
|
+
webhookConnection = new aws16.cloudwatch.EventConnection(
|
|
5663
5663
|
"wraps-inbound-webhook-connection",
|
|
5664
5664
|
{
|
|
5665
5665
|
name: "wraps-inbound-webhook-connection",
|
|
@@ -5673,7 +5673,7 @@ function createEventBridgeInboundResources(config2) {
|
|
|
5673
5673
|
}
|
|
5674
5674
|
}
|
|
5675
5675
|
);
|
|
5676
|
-
webhookApiDestination = new
|
|
5676
|
+
webhookApiDestination = new aws16.cloudwatch.EventApiDestination(
|
|
5677
5677
|
"wraps-inbound-webhook-destination",
|
|
5678
5678
|
{
|
|
5679
5679
|
name: "wraps-inbound-webhook-destination",
|
|
@@ -5684,7 +5684,7 @@ function createEventBridgeInboundResources(config2) {
|
|
|
5684
5684
|
invocationRateLimitPerSecond: 100
|
|
5685
5685
|
}
|
|
5686
5686
|
);
|
|
5687
|
-
const webhookRole = new
|
|
5687
|
+
const webhookRole = new aws16.iam.Role("wraps-inbound-webhook-role", {
|
|
5688
5688
|
name: "wraps-inbound-eventbridge-webhook-role",
|
|
5689
5689
|
assumeRolePolicy: JSON.stringify({
|
|
5690
5690
|
Version: "2012-10-17",
|
|
@@ -5703,7 +5703,7 @@ function createEventBridgeInboundResources(config2) {
|
|
|
5703
5703
|
Service: "email-inbound"
|
|
5704
5704
|
}
|
|
5705
5705
|
});
|
|
5706
|
-
new
|
|
5706
|
+
new aws16.iam.RolePolicy("wraps-inbound-webhook-policy", {
|
|
5707
5707
|
role: webhookRole.name,
|
|
5708
5708
|
policy: webhookApiDestination.arn.apply(
|
|
5709
5709
|
(destArn) => JSON.stringify({
|
|
@@ -5718,7 +5718,7 @@ function createEventBridgeInboundResources(config2) {
|
|
|
5718
5718
|
})
|
|
5719
5719
|
)
|
|
5720
5720
|
});
|
|
5721
|
-
webhookTarget = new
|
|
5721
|
+
webhookTarget = new aws16.cloudwatch.EventTarget(
|
|
5722
5722
|
"wraps-inbound-webhook-target",
|
|
5723
5723
|
{
|
|
5724
5724
|
rule: rule.name,
|
|
@@ -9419,13 +9419,12 @@ async function deleteCdnDNSRecords(hostedZoneId, customDomain) {
|
|
|
9419
9419
|
// src/commands/cdn/init.ts
|
|
9420
9420
|
init_esm_shims();
|
|
9421
9421
|
import * as clack10 from "@clack/prompts";
|
|
9422
|
-
import * as
|
|
9422
|
+
import * as pulumi5 from "@pulumi/pulumi";
|
|
9423
9423
|
import pc11 from "picocolors";
|
|
9424
9424
|
|
|
9425
9425
|
// src/infrastructure/cdn-stack.ts
|
|
9426
9426
|
init_esm_shims();
|
|
9427
|
-
import * as
|
|
9428
|
-
import * as pulumi3 from "@pulumi/pulumi";
|
|
9427
|
+
import * as pulumi4 from "@pulumi/pulumi";
|
|
9429
9428
|
|
|
9430
9429
|
// src/infrastructure/resources/s3-cdn.ts
|
|
9431
9430
|
init_esm_shims();
|
|
@@ -9749,19 +9748,133 @@ async function createCdnACMCertificate(config2) {
|
|
|
9749
9748
|
};
|
|
9750
9749
|
}
|
|
9751
9750
|
|
|
9752
|
-
// src/infrastructure/
|
|
9751
|
+
// src/infrastructure/shared/iam.ts
|
|
9752
|
+
init_esm_shims();
|
|
9753
9753
|
init_resource_checks();
|
|
9754
|
+
import * as aws2 from "@pulumi/aws";
|
|
9755
|
+
import * as pulumi3 from "@pulumi/pulumi";
|
|
9756
|
+
async function createServiceIAMRole(config2) {
|
|
9757
|
+
let assumeRolePolicy;
|
|
9758
|
+
if (config2.provider === "vercel" && config2.oidcProvider) {
|
|
9759
|
+
const hasAdditionalPrincipals = config2.additionalVercelPrincipals && config2.additionalVercelPrincipals.length > 0;
|
|
9760
|
+
if (hasAdditionalPrincipals) {
|
|
9761
|
+
const serviceStatement = JSON.stringify({
|
|
9762
|
+
Effect: "Allow",
|
|
9763
|
+
Principal: {
|
|
9764
|
+
Service: config2.additionalVercelPrincipals.length === 1 ? config2.additionalVercelPrincipals[0] : config2.additionalVercelPrincipals
|
|
9765
|
+
},
|
|
9766
|
+
Action: "sts:AssumeRole"
|
|
9767
|
+
});
|
|
9768
|
+
assumeRolePolicy = pulumi3.interpolate`{
|
|
9769
|
+
"Version": "2012-10-17",
|
|
9770
|
+
"Statement": [
|
|
9771
|
+
{
|
|
9772
|
+
"Effect": "Allow",
|
|
9773
|
+
"Principal": {
|
|
9774
|
+
"Federated": "${config2.oidcProvider.arn}"
|
|
9775
|
+
},
|
|
9776
|
+
"Action": "sts:AssumeRoleWithWebIdentity",
|
|
9777
|
+
"Condition": {
|
|
9778
|
+
"StringEquals": {
|
|
9779
|
+
"oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
|
|
9780
|
+
},
|
|
9781
|
+
"StringLike": {
|
|
9782
|
+
"oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
|
|
9783
|
+
}
|
|
9784
|
+
}
|
|
9785
|
+
},
|
|
9786
|
+
${serviceStatement}
|
|
9787
|
+
]
|
|
9788
|
+
}`;
|
|
9789
|
+
} else {
|
|
9790
|
+
assumeRolePolicy = pulumi3.interpolate`{
|
|
9791
|
+
"Version": "2012-10-17",
|
|
9792
|
+
"Statement": [{
|
|
9793
|
+
"Effect": "Allow",
|
|
9794
|
+
"Principal": {
|
|
9795
|
+
"Federated": "${config2.oidcProvider.arn}"
|
|
9796
|
+
},
|
|
9797
|
+
"Action": "sts:AssumeRoleWithWebIdentity",
|
|
9798
|
+
"Condition": {
|
|
9799
|
+
"StringEquals": {
|
|
9800
|
+
"oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
|
|
9801
|
+
},
|
|
9802
|
+
"StringLike": {
|
|
9803
|
+
"oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
|
|
9804
|
+
}
|
|
9805
|
+
}
|
|
9806
|
+
}]
|
|
9807
|
+
}`;
|
|
9808
|
+
}
|
|
9809
|
+
} else if (config2.provider === "aws") {
|
|
9810
|
+
assumeRolePolicy = pulumi3.output(`{
|
|
9811
|
+
"Version": "2012-10-17",
|
|
9812
|
+
"Statement": [{
|
|
9813
|
+
"Effect": "Allow",
|
|
9814
|
+
"Principal": {
|
|
9815
|
+
"Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
|
|
9816
|
+
},
|
|
9817
|
+
"Action": "sts:AssumeRole"
|
|
9818
|
+
}]
|
|
9819
|
+
}`);
|
|
9820
|
+
} else {
|
|
9821
|
+
throw new Error("Other providers not yet implemented");
|
|
9822
|
+
}
|
|
9823
|
+
const roleName = `wraps-${config2.serviceName}-role`;
|
|
9824
|
+
const exists = await roleExists(roleName);
|
|
9825
|
+
const tags = {
|
|
9826
|
+
ManagedBy: "wraps-cli",
|
|
9827
|
+
Provider: config2.provider,
|
|
9828
|
+
...config2.extraTags
|
|
9829
|
+
};
|
|
9830
|
+
const role = exists ? new aws2.iam.Role(
|
|
9831
|
+
roleName,
|
|
9832
|
+
{ name: roleName, assumeRolePolicy, tags },
|
|
9833
|
+
{
|
|
9834
|
+
import: roleName,
|
|
9835
|
+
...config2.customTimeouts && {
|
|
9836
|
+
customTimeouts: config2.customTimeouts
|
|
9837
|
+
}
|
|
9838
|
+
}
|
|
9839
|
+
) : new aws2.iam.Role(
|
|
9840
|
+
roleName,
|
|
9841
|
+
{ name: roleName, assumeRolePolicy, tags },
|
|
9842
|
+
config2.customTimeouts ? { customTimeouts: config2.customTimeouts } : void 0
|
|
9843
|
+
);
|
|
9844
|
+
const policyName = `wraps-${config2.serviceName}-policy`;
|
|
9845
|
+
const isOutputStatements = pulumi3.Output.isInstance(config2.policyStatements);
|
|
9846
|
+
if (isOutputStatements) {
|
|
9847
|
+
new aws2.iam.RolePolicy(policyName, {
|
|
9848
|
+
role: role.name,
|
|
9849
|
+
policy: config2.policyStatements.apply(
|
|
9850
|
+
(stmts) => JSON.stringify({
|
|
9851
|
+
Version: "2012-10-17",
|
|
9852
|
+
Statement: stmts
|
|
9853
|
+
})
|
|
9854
|
+
)
|
|
9855
|
+
});
|
|
9856
|
+
} else {
|
|
9857
|
+
new aws2.iam.RolePolicy(policyName, {
|
|
9858
|
+
role: role.name,
|
|
9859
|
+
policy: JSON.stringify({
|
|
9860
|
+
Version: "2012-10-17",
|
|
9861
|
+
Statement: config2.policyStatements
|
|
9862
|
+
})
|
|
9863
|
+
});
|
|
9864
|
+
}
|
|
9865
|
+
return role;
|
|
9866
|
+
}
|
|
9754
9867
|
|
|
9755
9868
|
// src/infrastructure/vercel-oidc.ts
|
|
9756
9869
|
init_esm_shims();
|
|
9757
|
-
import * as
|
|
9870
|
+
import * as aws3 from "@pulumi/aws";
|
|
9758
9871
|
async function getExistingOIDCProviderArn(url) {
|
|
9759
9872
|
try {
|
|
9760
9873
|
const { IAMClient: IAMClient4, ListOpenIDConnectProvidersCommand } = await import("@aws-sdk/client-iam");
|
|
9761
|
-
const
|
|
9874
|
+
const iam9 = new IAMClient4({
|
|
9762
9875
|
region: process.env.AWS_REGION || "us-east-1"
|
|
9763
9876
|
});
|
|
9764
|
-
const response = await
|
|
9877
|
+
const response = await iam9.send(new ListOpenIDConnectProvidersCommand({}));
|
|
9765
9878
|
const expectedArnSuffix = url.replace("https://", "");
|
|
9766
9879
|
const provider = response.OpenIDConnectProviderList?.find(
|
|
9767
9880
|
(p) => p.Arn?.endsWith(expectedArnSuffix)
|
|
@@ -9776,7 +9889,7 @@ async function createVercelOIDC(config2) {
|
|
|
9776
9889
|
const url = `https://oidc.vercel.com/${config2.teamSlug}`;
|
|
9777
9890
|
const existingArn = await getExistingOIDCProviderArn(url);
|
|
9778
9891
|
if (existingArn) {
|
|
9779
|
-
return new
|
|
9892
|
+
return new aws3.iam.OpenIdConnectProvider(
|
|
9780
9893
|
"wraps-vercel-oidc",
|
|
9781
9894
|
{
|
|
9782
9895
|
url,
|
|
@@ -9797,7 +9910,7 @@ async function createVercelOIDC(config2) {
|
|
|
9797
9910
|
}
|
|
9798
9911
|
);
|
|
9799
9912
|
}
|
|
9800
|
-
return new
|
|
9913
|
+
return new aws3.iam.OpenIdConnectProvider("wraps-vercel-oidc", {
|
|
9801
9914
|
url,
|
|
9802
9915
|
clientIdLists: [`https://vercel.com/${config2.teamSlug}`],
|
|
9803
9916
|
thumbprintLists: [
|
|
@@ -9814,104 +9927,46 @@ async function createVercelOIDC(config2) {
|
|
|
9814
9927
|
|
|
9815
9928
|
// src/infrastructure/cdn-stack.ts
|
|
9816
9929
|
async function createCdnIAMRole(config2) {
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
"
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
"
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
"oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
|
|
9833
|
-
}
|
|
9834
|
-
}
|
|
9835
|
-
}]
|
|
9836
|
-
}`;
|
|
9837
|
-
} else if (config2.provider === "aws") {
|
|
9838
|
-
assumeRolePolicy = pulumi3.output(`{
|
|
9839
|
-
"Version": "2012-10-17",
|
|
9840
|
-
"Statement": [{
|
|
9841
|
-
"Effect": "Allow",
|
|
9842
|
-
"Principal": {
|
|
9843
|
-
"Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
|
|
9844
|
-
},
|
|
9845
|
-
"Action": "sts:AssumeRole"
|
|
9846
|
-
}]
|
|
9847
|
-
}`);
|
|
9848
|
-
} else {
|
|
9849
|
-
throw new Error("Other providers not yet implemented");
|
|
9850
|
-
}
|
|
9851
|
-
const roleName = "wraps-cdn-role";
|
|
9852
|
-
const exists = await roleExists(roleName);
|
|
9853
|
-
const role = exists ? new aws3.iam.Role(
|
|
9854
|
-
roleName,
|
|
9855
|
-
{
|
|
9856
|
-
name: roleName,
|
|
9857
|
-
assumeRolePolicy,
|
|
9858
|
-
tags: {
|
|
9859
|
-
ManagedBy: "wraps-cli",
|
|
9860
|
-
Service: "cdn",
|
|
9861
|
-
Provider: config2.provider
|
|
9930
|
+
const resolvedStatements = pulumi4.all([config2.bucketArn, config2.distributionArn]).apply(([bucketArn, distributionArn]) => {
|
|
9931
|
+
const statements = [
|
|
9932
|
+
{
|
|
9933
|
+
Sid: "StorageBucketAccess",
|
|
9934
|
+
Effect: "Allow",
|
|
9935
|
+
Action: [
|
|
9936
|
+
"s3:PutObject",
|
|
9937
|
+
"s3:GetObject",
|
|
9938
|
+
"s3:DeleteObject",
|
|
9939
|
+
"s3:ListBucket",
|
|
9940
|
+
"s3:GetBucketLocation",
|
|
9941
|
+
"s3:GetObjectTagging",
|
|
9942
|
+
"s3:PutObjectTagging"
|
|
9943
|
+
],
|
|
9944
|
+
Resource: [bucketArn, `${bucketArn}/*`]
|
|
9862
9945
|
}
|
|
9863
|
-
|
|
9864
|
-
{
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9946
|
+
];
|
|
9947
|
+
if (distributionArn) {
|
|
9948
|
+
statements.push({
|
|
9949
|
+
Sid: "CloudFrontInvalidation",
|
|
9950
|
+
Effect: "Allow",
|
|
9951
|
+
Action: [
|
|
9952
|
+
"cloudfront:CreateInvalidation",
|
|
9953
|
+
"cloudfront:GetInvalidation",
|
|
9954
|
+
"cloudfront:ListInvalidations"
|
|
9955
|
+
],
|
|
9956
|
+
Resource: distributionArn
|
|
9957
|
+
});
|
|
9874
9958
|
}
|
|
9959
|
+
return statements;
|
|
9875
9960
|
});
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
"s3:DeleteObject",
|
|
9885
|
-
"s3:ListBucket",
|
|
9886
|
-
"s3:GetBucketLocation",
|
|
9887
|
-
"s3:GetObjectTagging",
|
|
9888
|
-
"s3:PutObjectTagging"
|
|
9889
|
-
],
|
|
9890
|
-
Resource: [config2.bucketArn, pulumi3.interpolate`${config2.bucketArn}/*`]
|
|
9891
|
-
}
|
|
9892
|
-
];
|
|
9893
|
-
if (config2.distributionArn) {
|
|
9894
|
-
statements.push({
|
|
9895
|
-
Sid: "CloudFrontInvalidation",
|
|
9896
|
-
Effect: "Allow",
|
|
9897
|
-
Action: [
|
|
9898
|
-
"cloudfront:CreateInvalidation",
|
|
9899
|
-
"cloudfront:GetInvalidation",
|
|
9900
|
-
"cloudfront:ListInvalidations"
|
|
9901
|
-
],
|
|
9902
|
-
Resource: config2.distributionArn
|
|
9903
|
-
});
|
|
9904
|
-
}
|
|
9905
|
-
new aws3.iam.RolePolicy("wraps-cdn-policy", {
|
|
9906
|
-
role: role.name,
|
|
9907
|
-
policy: pulumi3.all([statements]).apply(
|
|
9908
|
-
([stmts]) => JSON.stringify({
|
|
9909
|
-
Version: "2012-10-17",
|
|
9910
|
-
Statement: stmts
|
|
9911
|
-
})
|
|
9912
|
-
)
|
|
9961
|
+
return createServiceIAMRole({
|
|
9962
|
+
serviceName: "cdn",
|
|
9963
|
+
provider: config2.provider,
|
|
9964
|
+
oidcProvider: config2.oidcProvider,
|
|
9965
|
+
vercelTeamSlug: config2.vercelTeamSlug,
|
|
9966
|
+
vercelProjectName: config2.vercelProjectName,
|
|
9967
|
+
policyStatements: resolvedStatements,
|
|
9968
|
+
extraTags: { Service: "cdn" }
|
|
9913
9969
|
});
|
|
9914
|
-
return role;
|
|
9915
9970
|
}
|
|
9916
9971
|
async function deployCdnStack(config2) {
|
|
9917
9972
|
const accountId = config2.accountId;
|
|
@@ -9943,7 +9998,7 @@ async function deployCdnStack(config2) {
|
|
|
9943
9998
|
if (config2.cdnConfig.cdn.enabled) {
|
|
9944
9999
|
const hasAutoValidation2 = acmResources?.certificateValidation;
|
|
9945
10000
|
const useCertFromUpgrade = config2.certValidated && config2.existingCertArn;
|
|
9946
|
-
const certificateArn = useCertFromUpgrade ?
|
|
10001
|
+
const certificateArn = useCertFromUpgrade ? pulumi4.output(config2.existingCertArn) : hasAutoValidation2 ? acmResources?.certificateValidation?.certificateArn : void 0;
|
|
9947
10002
|
const customDomainForCdn = useCertFromUpgrade || hasAutoValidation2 ? config2.cdnConfig.cdn.customDomain : void 0;
|
|
9948
10003
|
cdnResources = await createCdnDistribution({
|
|
9949
10004
|
bucket: bucketResources.bucket,
|
|
@@ -10529,7 +10584,7 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
|
|
|
10529
10584
|
"Generating infrastructure preview",
|
|
10530
10585
|
async () => {
|
|
10531
10586
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
10532
|
-
const stack = await
|
|
10587
|
+
const stack = await pulumi5.automation.LocalWorkspace.createOrSelectStack(
|
|
10533
10588
|
{
|
|
10534
10589
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
10535
10590
|
projectName: "wraps-cdn",
|
|
@@ -10594,7 +10649,7 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
|
|
|
10594
10649
|
"Deploying CDN infrastructure (this may take 2-3 minutes)",
|
|
10595
10650
|
async () => {
|
|
10596
10651
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
10597
|
-
const stack = await
|
|
10652
|
+
const stack = await pulumi5.automation.LocalWorkspace.createOrSelectStack(
|
|
10598
10653
|
{
|
|
10599
10654
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
10600
10655
|
projectName: "wraps-cdn",
|
|
@@ -10929,7 +10984,7 @@ init_aws();
|
|
|
10929
10984
|
init_fs();
|
|
10930
10985
|
init_metadata();
|
|
10931
10986
|
import * as clack11 from "@clack/prompts";
|
|
10932
|
-
import * as
|
|
10987
|
+
import * as pulumi6 from "@pulumi/pulumi";
|
|
10933
10988
|
import pc12 from "picocolors";
|
|
10934
10989
|
async function cdnStatus(options) {
|
|
10935
10990
|
const startTime = Date.now();
|
|
@@ -10965,7 +11020,7 @@ async function cdnStatus(options) {
|
|
|
10965
11020
|
let stackOutputs = {};
|
|
10966
11021
|
try {
|
|
10967
11022
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
10968
|
-
const stack = await
|
|
11023
|
+
const stack = await pulumi6.automation.LocalWorkspace.selectStack({
|
|
10969
11024
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
10970
11025
|
workDir: getPulumiWorkDir()
|
|
10971
11026
|
});
|
|
@@ -11087,7 +11142,7 @@ ${pc12.bold("Commands:")}`);
|
|
|
11087
11142
|
// src/commands/cdn/sync.ts
|
|
11088
11143
|
init_esm_shims();
|
|
11089
11144
|
import * as clack12 from "@clack/prompts";
|
|
11090
|
-
import * as
|
|
11145
|
+
import * as pulumi7 from "@pulumi/pulumi";
|
|
11091
11146
|
import pc13 from "picocolors";
|
|
11092
11147
|
init_client();
|
|
11093
11148
|
init_events();
|
|
@@ -11143,7 +11198,7 @@ async function cdnSync(options) {
|
|
|
11143
11198
|
if (cdnConfig.cdn.customDomain) {
|
|
11144
11199
|
try {
|
|
11145
11200
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
11146
|
-
const checkStack = await
|
|
11201
|
+
const checkStack = await pulumi7.automation.LocalWorkspace.selectStack({
|
|
11147
11202
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
11148
11203
|
workDir: getPulumiWorkDir()
|
|
11149
11204
|
});
|
|
@@ -11180,7 +11235,7 @@ async function cdnSync(options) {
|
|
|
11180
11235
|
try {
|
|
11181
11236
|
await progress.execute("Syncing CDN infrastructure", async () => {
|
|
11182
11237
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
11183
|
-
const stack = await
|
|
11238
|
+
const stack = await pulumi7.automation.LocalWorkspace.createOrSelectStack(
|
|
11184
11239
|
{
|
|
11185
11240
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
11186
11241
|
projectName: "wraps-cdn",
|
|
@@ -11242,7 +11297,7 @@ async function cdnSync(options) {
|
|
|
11242
11297
|
// src/commands/cdn/upgrade.ts
|
|
11243
11298
|
init_esm_shims();
|
|
11244
11299
|
import * as clack13 from "@clack/prompts";
|
|
11245
|
-
import * as
|
|
11300
|
+
import * as pulumi8 from "@pulumi/pulumi";
|
|
11246
11301
|
import pc14 from "picocolors";
|
|
11247
11302
|
init_client();
|
|
11248
11303
|
init_events();
|
|
@@ -11298,7 +11353,7 @@ async function cdnUpgrade(options) {
|
|
|
11298
11353
|
let stackOutputs = {};
|
|
11299
11354
|
try {
|
|
11300
11355
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
11301
|
-
const stack = await
|
|
11356
|
+
const stack = await pulumi8.automation.LocalWorkspace.selectStack({
|
|
11302
11357
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
11303
11358
|
workDir: getPulumiWorkDir()
|
|
11304
11359
|
});
|
|
@@ -11436,7 +11491,7 @@ Ready to add custom domain: ${pc14.cyan(pendingDomain)}`);
|
|
|
11436
11491
|
"Updating CloudFront distribution (this may take 2-3 minutes)",
|
|
11437
11492
|
async () => {
|
|
11438
11493
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
11439
|
-
const stack = await
|
|
11494
|
+
const stack = await pulumi8.automation.LocalWorkspace.createOrSelectStack(
|
|
11440
11495
|
{
|
|
11441
11496
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
11442
11497
|
projectName: "wraps-cdn",
|
|
@@ -11524,7 +11579,7 @@ init_aws();
|
|
|
11524
11579
|
init_fs();
|
|
11525
11580
|
init_metadata();
|
|
11526
11581
|
import * as clack14 from "@clack/prompts";
|
|
11527
|
-
import * as
|
|
11582
|
+
import * as pulumi9 from "@pulumi/pulumi";
|
|
11528
11583
|
import pc15 from "picocolors";
|
|
11529
11584
|
async function checkDNSRecord(hostname, expectedValue) {
|
|
11530
11585
|
try {
|
|
@@ -11607,7 +11662,7 @@ async function cdnVerify(options) {
|
|
|
11607
11662
|
let stackOutputs = {};
|
|
11608
11663
|
try {
|
|
11609
11664
|
await ensurePulumiWorkDir({ accountId: identity.accountId, region });
|
|
11610
|
-
const stack = await
|
|
11665
|
+
const stack = await pulumi9.automation.LocalWorkspace.selectStack({
|
|
11611
11666
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
11612
11667
|
workDir: getPulumiWorkDir()
|
|
11613
11668
|
});
|
|
@@ -14754,7 +14809,7 @@ import pc17 from "picocolors";
|
|
|
14754
14809
|
// src/infrastructure/email-stack.ts
|
|
14755
14810
|
init_esm_shims();
|
|
14756
14811
|
init_dist();
|
|
14757
|
-
import * as
|
|
14812
|
+
import * as aws17 from "@pulumi/aws";
|
|
14758
14813
|
|
|
14759
14814
|
// src/infrastructure/resources/alerting.ts
|
|
14760
14815
|
init_esm_shims();
|
|
@@ -15022,7 +15077,7 @@ async function createDynamoDBTables(_config) {
|
|
|
15022
15077
|
// src/infrastructure/resources/eventbridge.ts
|
|
15023
15078
|
init_esm_shims();
|
|
15024
15079
|
import * as aws6 from "@pulumi/aws";
|
|
15025
|
-
import * as
|
|
15080
|
+
import * as pulumi10 from "@pulumi/pulumi";
|
|
15026
15081
|
async function createEventBridgeResources(config2) {
|
|
15027
15082
|
const eventBusName = config2.eventBusArn.apply((arn) => arn.split("/").pop());
|
|
15028
15083
|
const rule = new aws6.cloudwatch.EventRule("wraps-email-events-rule", {
|
|
@@ -15040,7 +15095,7 @@ async function createEventBridgeResources(config2) {
|
|
|
15040
15095
|
});
|
|
15041
15096
|
new aws6.sqs.QueuePolicy("wraps-email-events-queue-policy", {
|
|
15042
15097
|
queueUrl: config2.queueUrl,
|
|
15043
|
-
policy:
|
|
15098
|
+
policy: pulumi10.all([config2.queueArn, rule.arn]).apply(
|
|
15044
15099
|
([queueArn, ruleArn]) => JSON.stringify({
|
|
15045
15100
|
Version: "2012-10-17",
|
|
15046
15101
|
Statement: [
|
|
@@ -15149,68 +15204,7 @@ async function createEventBridgeResources(config2) {
|
|
|
15149
15204
|
|
|
15150
15205
|
// src/infrastructure/resources/iam.ts
|
|
15151
15206
|
init_esm_shims();
|
|
15152
|
-
init_resource_checks();
|
|
15153
|
-
import * as aws7 from "@pulumi/aws";
|
|
15154
|
-
import * as pulumi10 from "@pulumi/pulumi";
|
|
15155
15207
|
async function createIAMRole(config2) {
|
|
15156
|
-
let assumeRolePolicy;
|
|
15157
|
-
if (config2.provider === "vercel" && config2.oidcProvider) {
|
|
15158
|
-
assumeRolePolicy = pulumi10.interpolate`{
|
|
15159
|
-
"Version": "2012-10-17",
|
|
15160
|
-
"Statement": [{
|
|
15161
|
-
"Effect": "Allow",
|
|
15162
|
-
"Principal": {
|
|
15163
|
-
"Federated": "${config2.oidcProvider.arn}"
|
|
15164
|
-
},
|
|
15165
|
-
"Action": "sts:AssumeRoleWithWebIdentity",
|
|
15166
|
-
"Condition": {
|
|
15167
|
-
"StringEquals": {
|
|
15168
|
-
"oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
|
|
15169
|
-
},
|
|
15170
|
-
"StringLike": {
|
|
15171
|
-
"oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
|
|
15172
|
-
}
|
|
15173
|
-
}
|
|
15174
|
-
}]
|
|
15175
|
-
}`;
|
|
15176
|
-
} else if (config2.provider === "aws") {
|
|
15177
|
-
assumeRolePolicy = pulumi10.output(`{
|
|
15178
|
-
"Version": "2012-10-17",
|
|
15179
|
-
"Statement": [{
|
|
15180
|
-
"Effect": "Allow",
|
|
15181
|
-
"Principal": {
|
|
15182
|
-
"Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
|
|
15183
|
-
},
|
|
15184
|
-
"Action": "sts:AssumeRole"
|
|
15185
|
-
}]
|
|
15186
|
-
}`);
|
|
15187
|
-
} else {
|
|
15188
|
-
throw new Error("Other providers not yet implemented");
|
|
15189
|
-
}
|
|
15190
|
-
const roleName = "wraps-email-role";
|
|
15191
|
-
const exists = await roleExists(roleName);
|
|
15192
|
-
const role = exists ? new aws7.iam.Role(
|
|
15193
|
-
roleName,
|
|
15194
|
-
{
|
|
15195
|
-
name: roleName,
|
|
15196
|
-
assumeRolePolicy,
|
|
15197
|
-
tags: {
|
|
15198
|
-
ManagedBy: "wraps-cli",
|
|
15199
|
-
Provider: config2.provider
|
|
15200
|
-
}
|
|
15201
|
-
},
|
|
15202
|
-
{
|
|
15203
|
-
import: roleName
|
|
15204
|
-
// Import existing role (use role name, not ARN)
|
|
15205
|
-
}
|
|
15206
|
-
) : new aws7.iam.Role(roleName, {
|
|
15207
|
-
name: roleName,
|
|
15208
|
-
assumeRolePolicy,
|
|
15209
|
-
tags: {
|
|
15210
|
-
ManagedBy: "wraps-cli",
|
|
15211
|
-
Provider: config2.provider
|
|
15212
|
-
}
|
|
15213
|
-
});
|
|
15214
15208
|
const statements = [];
|
|
15215
15209
|
statements.push({
|
|
15216
15210
|
Effect: "Allow",
|
|
@@ -15316,14 +15310,14 @@ async function createIAMRole(config2) {
|
|
|
15316
15310
|
Resource: "arn:aws:ses:*:*:mailmanager-archive/*"
|
|
15317
15311
|
});
|
|
15318
15312
|
}
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15313
|
+
return createServiceIAMRole({
|
|
15314
|
+
serviceName: "email",
|
|
15315
|
+
provider: config2.provider,
|
|
15316
|
+
oidcProvider: config2.oidcProvider,
|
|
15317
|
+
vercelTeamSlug: config2.vercelTeamSlug,
|
|
15318
|
+
vercelProjectName: config2.vercelProjectName,
|
|
15319
|
+
policyStatements: statements
|
|
15325
15320
|
});
|
|
15326
|
-
return role;
|
|
15327
15321
|
}
|
|
15328
15322
|
|
|
15329
15323
|
// src/infrastructure/email-stack.ts
|
|
@@ -15331,7 +15325,7 @@ init_lambda();
|
|
|
15331
15325
|
|
|
15332
15326
|
// src/infrastructure/resources/ses.ts
|
|
15333
15327
|
init_esm_shims();
|
|
15334
|
-
import * as
|
|
15328
|
+
import * as aws8 from "@pulumi/aws";
|
|
15335
15329
|
async function configurationSetExists(configSetName, region) {
|
|
15336
15330
|
try {
|
|
15337
15331
|
const { SESv2Client: SESv2Client6, GetConfigurationSetCommand: GetConfigurationSetCommand2 } = await import("@aws-sdk/client-sesv2");
|
|
@@ -15409,16 +15403,16 @@ async function createSESResources(config2) {
|
|
|
15409
15403
|
}
|
|
15410
15404
|
const configSetName = "wraps-email-tracking";
|
|
15411
15405
|
const exists = await configurationSetExists(configSetName, config2.region);
|
|
15412
|
-
const configSet = exists ? new
|
|
15406
|
+
const configSet = exists ? new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions, {
|
|
15413
15407
|
import: configSetName
|
|
15414
15408
|
// Import existing configuration set
|
|
15415
|
-
}) : new
|
|
15416
|
-
const defaultEventBus =
|
|
15409
|
+
}) : new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions);
|
|
15410
|
+
const defaultEventBus = aws8.cloudwatch.getEventBusOutput({
|
|
15417
15411
|
name: "default"
|
|
15418
15412
|
});
|
|
15419
15413
|
if (config2.eventTrackingEnabled) {
|
|
15420
15414
|
const eventDestName = "wraps-email-eventbridge";
|
|
15421
|
-
new
|
|
15415
|
+
new aws8.sesv2.ConfigurationSetEventDestination(
|
|
15422
15416
|
"wraps-email-all-events",
|
|
15423
15417
|
{
|
|
15424
15418
|
configurationSetName: configSet.configurationSetName,
|
|
@@ -15458,7 +15452,7 @@ async function createSESResources(config2) {
|
|
|
15458
15452
|
config2.domain,
|
|
15459
15453
|
config2.region
|
|
15460
15454
|
);
|
|
15461
|
-
domainIdentity = identityExists ? new
|
|
15455
|
+
domainIdentity = identityExists ? new aws8.sesv2.EmailIdentity(
|
|
15462
15456
|
"wraps-email-domain",
|
|
15463
15457
|
{
|
|
15464
15458
|
emailIdentity: config2.domain,
|
|
@@ -15475,7 +15469,7 @@ async function createSESResources(config2) {
|
|
|
15475
15469
|
import: config2.domain
|
|
15476
15470
|
// Import existing identity
|
|
15477
15471
|
}
|
|
15478
|
-
) : new
|
|
15472
|
+
) : new aws8.sesv2.EmailIdentity("wraps-email-domain", {
|
|
15479
15473
|
emailIdentity: config2.domain,
|
|
15480
15474
|
configurationSetName: configSet.configurationSetName,
|
|
15481
15475
|
// Link configuration set to domain
|
|
@@ -15491,7 +15485,7 @@ async function createSESResources(config2) {
|
|
|
15491
15485
|
);
|
|
15492
15486
|
if (config2.mailFromDomain) {
|
|
15493
15487
|
mailFromDomain = config2.mailFromDomain;
|
|
15494
|
-
new
|
|
15488
|
+
new aws8.sesv2.EmailIdentityMailFromAttributes(
|
|
15495
15489
|
"wraps-email-mail-from",
|
|
15496
15490
|
{
|
|
15497
15491
|
emailIdentity: config2.domain,
|
|
@@ -15522,7 +15516,7 @@ async function createSESResources(config2) {
|
|
|
15522
15516
|
// src/infrastructure/resources/smtp-credentials.ts
|
|
15523
15517
|
init_esm_shims();
|
|
15524
15518
|
import { createHmac as createHmac2 } from "crypto";
|
|
15525
|
-
import * as
|
|
15519
|
+
import * as aws9 from "@pulumi/aws";
|
|
15526
15520
|
function convertToSMTPPassword2(secretAccessKey, region) {
|
|
15527
15521
|
const DATE = "11111111";
|
|
15528
15522
|
const SERVICE = "ses";
|
|
@@ -15543,10 +15537,10 @@ function convertToSMTPPassword2(secretAccessKey, region) {
|
|
|
15543
15537
|
async function userExists(userName) {
|
|
15544
15538
|
try {
|
|
15545
15539
|
const { IAMClient: IAMClient4, GetUserCommand } = await import("@aws-sdk/client-iam");
|
|
15546
|
-
const
|
|
15540
|
+
const iam9 = new IAMClient4({
|
|
15547
15541
|
region: process.env.AWS_REGION || "us-east-1"
|
|
15548
15542
|
});
|
|
15549
|
-
await
|
|
15543
|
+
await iam9.send(new GetUserCommand({ UserName: userName }));
|
|
15550
15544
|
return true;
|
|
15551
15545
|
} catch (error) {
|
|
15552
15546
|
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity") {
|
|
@@ -15558,7 +15552,7 @@ async function userExists(userName) {
|
|
|
15558
15552
|
async function createSMTPCredentials(config2) {
|
|
15559
15553
|
const userName = "wraps-email-smtp-user";
|
|
15560
15554
|
const userAlreadyExists = await userExists(userName);
|
|
15561
|
-
const iamUser = userAlreadyExists ? new
|
|
15555
|
+
const iamUser = userAlreadyExists ? new aws9.iam.User(
|
|
15562
15556
|
userName,
|
|
15563
15557
|
{
|
|
15564
15558
|
name: userName,
|
|
@@ -15568,14 +15562,14 @@ async function createSMTPCredentials(config2) {
|
|
|
15568
15562
|
}
|
|
15569
15563
|
},
|
|
15570
15564
|
{ import: userName }
|
|
15571
|
-
) : new
|
|
15565
|
+
) : new aws9.iam.User(userName, {
|
|
15572
15566
|
name: userName,
|
|
15573
15567
|
tags: {
|
|
15574
15568
|
ManagedBy: "wraps-cli",
|
|
15575
15569
|
Purpose: "SES SMTP Authentication"
|
|
15576
15570
|
}
|
|
15577
15571
|
});
|
|
15578
|
-
new
|
|
15572
|
+
new aws9.iam.UserPolicy("wraps-email-smtp-policy", {
|
|
15579
15573
|
user: iamUser.name,
|
|
15580
15574
|
policy: JSON.stringify({
|
|
15581
15575
|
Version: "2012-10-17",
|
|
@@ -15593,7 +15587,7 @@ async function createSMTPCredentials(config2) {
|
|
|
15593
15587
|
]
|
|
15594
15588
|
})
|
|
15595
15589
|
});
|
|
15596
|
-
const accessKey = new
|
|
15590
|
+
const accessKey = new aws9.iam.AccessKey("wraps-email-smtp-key", {
|
|
15597
15591
|
user: iamUser.name
|
|
15598
15592
|
});
|
|
15599
15593
|
const smtpPassword = accessKey.secret.apply(
|
|
@@ -15608,9 +15602,9 @@ async function createSMTPCredentials(config2) {
|
|
|
15608
15602
|
|
|
15609
15603
|
// src/infrastructure/resources/sqs.ts
|
|
15610
15604
|
init_esm_shims();
|
|
15611
|
-
import * as
|
|
15605
|
+
import * as aws10 from "@pulumi/aws";
|
|
15612
15606
|
async function createSQSResources() {
|
|
15613
|
-
const dlq = new
|
|
15607
|
+
const dlq = new aws10.sqs.Queue("wraps-email-events-dlq", {
|
|
15614
15608
|
name: "wraps-email-events-dlq",
|
|
15615
15609
|
messageRetentionSeconds: 1209600,
|
|
15616
15610
|
// 14 days
|
|
@@ -15619,7 +15613,7 @@ async function createSQSResources() {
|
|
|
15619
15613
|
Description: "Dead letter queue for failed SES event processing"
|
|
15620
15614
|
}
|
|
15621
15615
|
});
|
|
15622
|
-
const queue = new
|
|
15616
|
+
const queue = new aws10.sqs.Queue("wraps-email-events", {
|
|
15623
15617
|
name: "wraps-email-events",
|
|
15624
15618
|
visibilityTimeoutSeconds: 60,
|
|
15625
15619
|
// Must be >= Lambda timeout
|
|
@@ -15647,7 +15641,7 @@ async function createSQSResources() {
|
|
|
15647
15641
|
|
|
15648
15642
|
// src/infrastructure/email-stack.ts
|
|
15649
15643
|
async function deployEmailStack(config2) {
|
|
15650
|
-
const identity = await
|
|
15644
|
+
const identity = await aws17.getCallerIdentity();
|
|
15651
15645
|
const accountId = identity.accountId;
|
|
15652
15646
|
let oidcProvider;
|
|
15653
15647
|
if (config2.provider === "vercel" && config2.vercel) {
|
|
@@ -15810,7 +15804,7 @@ async function deployEmailStack(config2) {
|
|
|
15810
15804
|
region: config2.region,
|
|
15811
15805
|
dlqArn: sqsInbound.dlq.arn
|
|
15812
15806
|
});
|
|
15813
|
-
new
|
|
15807
|
+
new aws17.s3.BucketNotification(
|
|
15814
15808
|
"wraps-inbound-s3-notification",
|
|
15815
15809
|
{
|
|
15816
15810
|
bucket: s3Inbound.bucket.id,
|
|
@@ -16323,13 +16317,13 @@ async function scanLambdaFunctions(region) {
|
|
|
16323
16317
|
}
|
|
16324
16318
|
}
|
|
16325
16319
|
async function scanIAMRoles(region) {
|
|
16326
|
-
const
|
|
16320
|
+
const iam9 = new IAMClient({ region });
|
|
16327
16321
|
const roles = [];
|
|
16328
16322
|
try {
|
|
16329
16323
|
let marker;
|
|
16330
16324
|
let hasMore = true;
|
|
16331
16325
|
while (hasMore) {
|
|
16332
|
-
const listResponse = await
|
|
16326
|
+
const listResponse = await iam9.send(
|
|
16333
16327
|
new ListRolesCommand({
|
|
16334
16328
|
Marker: marker,
|
|
16335
16329
|
MaxItems: 100
|
|
@@ -16757,7 +16751,7 @@ async function getEmailIdentityInfo(domain, region) {
|
|
|
16757
16751
|
mailFromDomain: response.MailFromAttributes?.MailFromDomain
|
|
16758
16752
|
};
|
|
16759
16753
|
} catch (error) {
|
|
16760
|
-
if (
|
|
16754
|
+
if (isAWSNotFoundError(error)) {
|
|
16761
16755
|
return { dkimTokens: [] };
|
|
16762
16756
|
}
|
|
16763
16757
|
throw error;
|
|
@@ -17549,11 +17543,11 @@ Run ${pc20.cyan("wraps email domains add")} to add a domain.
|
|
|
17549
17543
|
verified: details.VerifiedForSendingStatus,
|
|
17550
17544
|
dkimStatus: details.DkimAttributes?.Status || "PENDING"
|
|
17551
17545
|
};
|
|
17552
|
-
} catch {
|
|
17546
|
+
} catch (error) {
|
|
17553
17547
|
return {
|
|
17554
17548
|
name: domain.IdentityName,
|
|
17555
17549
|
verified: false,
|
|
17556
|
-
dkimStatus: "UNKNOWN"
|
|
17550
|
+
dkimStatus: isAWSNotFoundError(error) ? "UNKNOWN" : "ERROR"
|
|
17557
17551
|
};
|
|
17558
17552
|
}
|
|
17559
17553
|
})
|
|
@@ -19415,7 +19409,7 @@ Run ${pc24.cyan("wraps email init")} to deploy email infrastructure.
|
|
|
19415
19409
|
purpose: tracked?.purpose
|
|
19416
19410
|
};
|
|
19417
19411
|
} catch (error) {
|
|
19418
|
-
if (
|
|
19412
|
+
if (isAWSNotFoundError(error)) {
|
|
19419
19413
|
return {
|
|
19420
19414
|
domain: d.domain,
|
|
19421
19415
|
status: d.verified ? "verified" : "pending",
|
|
@@ -22459,9 +22453,9 @@ ${pc28.green("\u2713")} ${pc28.bold("Upgrade complete!")}
|
|
|
22459
22453
|
iamUserArn: outputs.smtpUserArn,
|
|
22460
22454
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22461
22455
|
};
|
|
22462
|
-
await saveConnectionMetadata(metadata);
|
|
22463
22456
|
}
|
|
22464
22457
|
}
|
|
22458
|
+
await saveConnectionMetadata(metadata);
|
|
22465
22459
|
const enabledFeatures = [];
|
|
22466
22460
|
if (updatedConfig.tracking?.enabled) {
|
|
22467
22461
|
enabledFeatures.push("tracking");
|
|
@@ -24574,10 +24568,10 @@ async function deployEventBridge(metadata, region, identity, webhookSecret, prog
|
|
|
24574
24568
|
var WRAPS_PLATFORM_ACCOUNT_ID = "905130073023";
|
|
24575
24569
|
async function updatePlatformRole(metadata, progress, externalId) {
|
|
24576
24570
|
const roleName = "wraps-console-access-role";
|
|
24577
|
-
const
|
|
24571
|
+
const iam9 = new IAMClient2({ region: "us-east-1" });
|
|
24578
24572
|
let roleExists2 = false;
|
|
24579
24573
|
try {
|
|
24580
|
-
await
|
|
24574
|
+
await iam9.send(new GetRoleCommand({ RoleName: roleName }));
|
|
24581
24575
|
roleExists2 = true;
|
|
24582
24576
|
} catch (error) {
|
|
24583
24577
|
const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
|
|
@@ -24590,7 +24584,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
|
|
|
24590
24584
|
const policy = buildConsolePolicyDocument(emailConfig, smsConfig);
|
|
24591
24585
|
if (roleExists2) {
|
|
24592
24586
|
await progress.execute("Updating platform access role", async () => {
|
|
24593
|
-
await
|
|
24587
|
+
await iam9.send(
|
|
24594
24588
|
new PutRolePolicyCommand({
|
|
24595
24589
|
RoleName: roleName,
|
|
24596
24590
|
PolicyName: "wraps-console-access-policy",
|
|
@@ -24618,7 +24612,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
|
|
|
24618
24612
|
}
|
|
24619
24613
|
]
|
|
24620
24614
|
};
|
|
24621
|
-
await
|
|
24615
|
+
await iam9.send(
|
|
24622
24616
|
new CreateRoleCommand({
|
|
24623
24617
|
RoleName: roleName,
|
|
24624
24618
|
Description: "Allows Wraps dashboard to access CloudWatch metrics and SES data",
|
|
@@ -24629,7 +24623,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
|
|
|
24629
24623
|
]
|
|
24630
24624
|
})
|
|
24631
24625
|
);
|
|
24632
|
-
await
|
|
24626
|
+
await iam9.send(
|
|
24633
24627
|
new PutRolePolicyCommand({
|
|
24634
24628
|
RoleName: roleName,
|
|
24635
24629
|
PolicyName: "wraps-console-access-policy",
|
|
@@ -25045,10 +25039,10 @@ Run ${pc33.cyan("wraps email init")} or ${pc33.cyan("wraps sms init")} first.
|
|
|
25045
25039
|
progress.succeed("Event streaming already configured");
|
|
25046
25040
|
}
|
|
25047
25041
|
const roleName = "wraps-console-access-role";
|
|
25048
|
-
const
|
|
25042
|
+
const iam9 = new IAMClient2({ region: "us-east-1" });
|
|
25049
25043
|
let roleExists2 = false;
|
|
25050
25044
|
try {
|
|
25051
|
-
await
|
|
25045
|
+
await iam9.send(new GetRoleCommand({ RoleName: roleName }));
|
|
25052
25046
|
roleExists2 = true;
|
|
25053
25047
|
} catch (error) {
|
|
25054
25048
|
const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
|
|
@@ -25061,7 +25055,7 @@ Run ${pc33.cyan("wraps email init")} or ${pc33.cyan("wraps sms init")} first.
|
|
|
25061
25055
|
const smsConfig = metadata.services.sms?.config;
|
|
25062
25056
|
const policy = buildConsolePolicyDocument(emailConfig, smsConfig);
|
|
25063
25057
|
await progress.execute("Updating platform access role", async () => {
|
|
25064
|
-
await
|
|
25058
|
+
await iam9.send(
|
|
25065
25059
|
new PutRolePolicyCommand({
|
|
25066
25060
|
RoleName: roleName,
|
|
25067
25061
|
PolicyName: "wraps-console-access-policy",
|
|
@@ -25212,10 +25206,10 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
25212
25206
|
process.exit(1);
|
|
25213
25207
|
}
|
|
25214
25208
|
const roleName = "wraps-console-access-role";
|
|
25215
|
-
const
|
|
25209
|
+
const iam9 = new IAMClient3({ region: "us-east-1" });
|
|
25216
25210
|
let roleExists2 = false;
|
|
25217
25211
|
try {
|
|
25218
|
-
await
|
|
25212
|
+
await iam9.send(new GetRoleCommand2({ RoleName: roleName }));
|
|
25219
25213
|
roleExists2 = true;
|
|
25220
25214
|
} catch (error) {
|
|
25221
25215
|
const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
|
|
@@ -25284,7 +25278,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
25284
25278
|
}
|
|
25285
25279
|
]
|
|
25286
25280
|
};
|
|
25287
|
-
await
|
|
25281
|
+
await iam9.send(
|
|
25288
25282
|
new CreateRoleCommand2({
|
|
25289
25283
|
RoleName: roleName,
|
|
25290
25284
|
Description: "Allows Wraps dashboard to access CloudWatch metrics and SES data",
|
|
@@ -25296,7 +25290,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
25296
25290
|
})
|
|
25297
25291
|
);
|
|
25298
25292
|
const { PutRolePolicyCommand: PutRolePolicyCommand2 } = await import("@aws-sdk/client-iam");
|
|
25299
|
-
await
|
|
25293
|
+
await iam9.send(
|
|
25300
25294
|
new PutRolePolicyCommand2({
|
|
25301
25295
|
RoleName: roleName,
|
|
25302
25296
|
PolicyName: "wraps-console-access-policy",
|
|
@@ -25307,7 +25301,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
25307
25301
|
} else {
|
|
25308
25302
|
await progress.execute("Updating IAM role permissions", async () => {
|
|
25309
25303
|
const { PutRolePolicyCommand: PutRolePolicyCommand2 } = await import("@aws-sdk/client-iam");
|
|
25310
|
-
await
|
|
25304
|
+
await iam9.send(
|
|
25311
25305
|
new PutRolePolicyCommand2({
|
|
25312
25306
|
RoleName: roleName,
|
|
25313
25307
|
PolicyName: "wraps-console-access-policy",
|
|
@@ -28501,85 +28495,10 @@ import pc39 from "picocolors";
|
|
|
28501
28495
|
|
|
28502
28496
|
// src/infrastructure/sms-stack.ts
|
|
28503
28497
|
init_esm_shims();
|
|
28504
|
-
|
|
28505
|
-
import * as aws19 from "@pulumi/aws";
|
|
28498
|
+
import * as aws18 from "@pulumi/aws";
|
|
28506
28499
|
import * as pulumi24 from "@pulumi/pulumi";
|
|
28500
|
+
init_resource_checks();
|
|
28507
28501
|
async function createSMSIAMRole(config2) {
|
|
28508
|
-
let assumeRolePolicy;
|
|
28509
|
-
if (config2.provider === "vercel" && config2.oidcProvider) {
|
|
28510
|
-
assumeRolePolicy = pulumi24.interpolate`{
|
|
28511
|
-
"Version": "2012-10-17",
|
|
28512
|
-
"Statement": [
|
|
28513
|
-
{
|
|
28514
|
-
"Effect": "Allow",
|
|
28515
|
-
"Principal": {
|
|
28516
|
-
"Federated": "${config2.oidcProvider.arn}"
|
|
28517
|
-
},
|
|
28518
|
-
"Action": "sts:AssumeRoleWithWebIdentity",
|
|
28519
|
-
"Condition": {
|
|
28520
|
-
"StringEquals": {
|
|
28521
|
-
"oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
|
|
28522
|
-
},
|
|
28523
|
-
"StringLike": {
|
|
28524
|
-
"oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
|
|
28525
|
-
}
|
|
28526
|
-
}
|
|
28527
|
-
},
|
|
28528
|
-
{
|
|
28529
|
-
"Effect": "Allow",
|
|
28530
|
-
"Principal": {
|
|
28531
|
-
"Service": "lambda.amazonaws.com"
|
|
28532
|
-
},
|
|
28533
|
-
"Action": "sts:AssumeRole"
|
|
28534
|
-
}
|
|
28535
|
-
]
|
|
28536
|
-
}`;
|
|
28537
|
-
} else if (config2.provider === "aws") {
|
|
28538
|
-
assumeRolePolicy = pulumi24.output(`{
|
|
28539
|
-
"Version": "2012-10-17",
|
|
28540
|
-
"Statement": [{
|
|
28541
|
-
"Effect": "Allow",
|
|
28542
|
-
"Principal": {
|
|
28543
|
-
"Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
|
|
28544
|
-
},
|
|
28545
|
-
"Action": "sts:AssumeRole"
|
|
28546
|
-
}]
|
|
28547
|
-
}`);
|
|
28548
|
-
} else {
|
|
28549
|
-
throw new Error("Other providers not yet implemented");
|
|
28550
|
-
}
|
|
28551
|
-
const roleName = "wraps-sms-role";
|
|
28552
|
-
const exists = await roleExists(roleName);
|
|
28553
|
-
const role = exists ? new aws19.iam.Role(
|
|
28554
|
-
roleName,
|
|
28555
|
-
{
|
|
28556
|
-
name: roleName,
|
|
28557
|
-
assumeRolePolicy,
|
|
28558
|
-
tags: {
|
|
28559
|
-
ManagedBy: "wraps-cli",
|
|
28560
|
-
Service: "sms",
|
|
28561
|
-
Provider: config2.provider
|
|
28562
|
-
}
|
|
28563
|
-
},
|
|
28564
|
-
{
|
|
28565
|
-
import: roleName,
|
|
28566
|
-
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28567
|
-
}
|
|
28568
|
-
) : new aws19.iam.Role(
|
|
28569
|
-
roleName,
|
|
28570
|
-
{
|
|
28571
|
-
name: roleName,
|
|
28572
|
-
assumeRolePolicy,
|
|
28573
|
-
tags: {
|
|
28574
|
-
ManagedBy: "wraps-cli",
|
|
28575
|
-
Service: "sms",
|
|
28576
|
-
Provider: config2.provider
|
|
28577
|
-
}
|
|
28578
|
-
},
|
|
28579
|
-
{
|
|
28580
|
-
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28581
|
-
}
|
|
28582
|
-
);
|
|
28583
28502
|
const statements = [];
|
|
28584
28503
|
statements.push({
|
|
28585
28504
|
Effect: "Allow",
|
|
@@ -28660,17 +28579,20 @@ async function createSMSIAMRole(config2) {
|
|
|
28660
28579
|
Resource: "arn:aws:logs:*:*:log-group:/aws/lambda/wraps-sms-*"
|
|
28661
28580
|
});
|
|
28662
28581
|
}
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
|
|
28667
|
-
|
|
28668
|
-
|
|
28582
|
+
return createServiceIAMRole({
|
|
28583
|
+
serviceName: "sms",
|
|
28584
|
+
provider: config2.provider,
|
|
28585
|
+
oidcProvider: config2.oidcProvider,
|
|
28586
|
+
vercelTeamSlug: config2.vercelTeamSlug,
|
|
28587
|
+
vercelProjectName: config2.vercelProjectName,
|
|
28588
|
+
additionalVercelPrincipals: ["lambda.amazonaws.com"],
|
|
28589
|
+
policyStatements: statements,
|
|
28590
|
+
extraTags: { Service: "sms" },
|
|
28591
|
+
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28669
28592
|
});
|
|
28670
|
-
return role;
|
|
28671
28593
|
}
|
|
28672
28594
|
function createSMSConfigurationSet() {
|
|
28673
|
-
return new
|
|
28595
|
+
return new aws18.pinpoint.Smsvoicev2ConfigurationSet("wraps-sms-config", {
|
|
28674
28596
|
name: "wraps-sms-config",
|
|
28675
28597
|
defaultMessageType: "TRANSACTIONAL",
|
|
28676
28598
|
tags: {
|
|
@@ -28680,7 +28602,7 @@ function createSMSConfigurationSet() {
|
|
|
28680
28602
|
});
|
|
28681
28603
|
}
|
|
28682
28604
|
function createSMSOptOutList() {
|
|
28683
|
-
return new
|
|
28605
|
+
return new aws18.pinpoint.Smsvoicev2OptOutList("wraps-sms-optouts", {
|
|
28684
28606
|
name: "wraps-sms-optouts",
|
|
28685
28607
|
tags: {
|
|
28686
28608
|
ManagedBy: "wraps-cli",
|
|
@@ -28744,7 +28666,7 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
|
|
|
28744
28666
|
}
|
|
28745
28667
|
};
|
|
28746
28668
|
if (existingArn) {
|
|
28747
|
-
return new
|
|
28669
|
+
return new aws18.pinpoint.Smsvoicev2PhoneNumber(
|
|
28748
28670
|
"wraps-sms-number",
|
|
28749
28671
|
phoneConfig,
|
|
28750
28672
|
{
|
|
@@ -28753,7 +28675,7 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
|
|
|
28753
28675
|
}
|
|
28754
28676
|
);
|
|
28755
28677
|
}
|
|
28756
|
-
return new
|
|
28678
|
+
return new aws18.pinpoint.Smsvoicev2PhoneNumber(
|
|
28757
28679
|
"wraps-sms-number",
|
|
28758
28680
|
phoneConfig,
|
|
28759
28681
|
{
|
|
@@ -28782,10 +28704,10 @@ async function createSMSSQSResources() {
|
|
|
28782
28704
|
Description: "Dead letter queue for failed SMS event processing"
|
|
28783
28705
|
}
|
|
28784
28706
|
};
|
|
28785
|
-
const dlq = dlqUrl ? new
|
|
28707
|
+
const dlq = dlqUrl ? new aws18.sqs.Queue(dlqName, dlqConfig, {
|
|
28786
28708
|
import: dlqUrl,
|
|
28787
28709
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28788
|
-
}) : new
|
|
28710
|
+
}) : new aws18.sqs.Queue(dlqName, dlqConfig, {
|
|
28789
28711
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28790
28712
|
});
|
|
28791
28713
|
const queueConfig = {
|
|
@@ -28808,10 +28730,10 @@ async function createSMSSQSResources() {
|
|
|
28808
28730
|
Description: "Queue for SMS events from SNS"
|
|
28809
28731
|
}
|
|
28810
28732
|
};
|
|
28811
|
-
const queue = queueUrl ? new
|
|
28733
|
+
const queue = queueUrl ? new aws18.sqs.Queue(queueName, queueConfig, {
|
|
28812
28734
|
import: queueUrl,
|
|
28813
28735
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28814
|
-
}) : new
|
|
28736
|
+
}) : new aws18.sqs.Queue(queueName, queueConfig, {
|
|
28815
28737
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28816
28738
|
});
|
|
28817
28739
|
return { queue, dlq };
|
|
@@ -28827,13 +28749,13 @@ async function createSMSSNSResources(config2) {
|
|
|
28827
28749
|
Description: "SNS topic for SMS delivery events"
|
|
28828
28750
|
}
|
|
28829
28751
|
};
|
|
28830
|
-
const topic = topicArn ? new
|
|
28752
|
+
const topic = topicArn ? new aws18.sns.Topic("wraps-sms-events-topic", topicConfig, {
|
|
28831
28753
|
import: topicArn,
|
|
28832
28754
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28833
|
-
}) : new
|
|
28755
|
+
}) : new aws18.sns.Topic("wraps-sms-events-topic", topicConfig, {
|
|
28834
28756
|
customTimeouts: { create: "2m", update: "2m", delete: "2m" }
|
|
28835
28757
|
});
|
|
28836
|
-
new
|
|
28758
|
+
new aws18.sns.TopicPolicy("wraps-sms-events-topic-policy", {
|
|
28837
28759
|
arn: topic.arn,
|
|
28838
28760
|
policy: topic.arn.apply(
|
|
28839
28761
|
(topicArn2) => JSON.stringify({
|
|
@@ -28850,7 +28772,7 @@ async function createSMSSNSResources(config2) {
|
|
|
28850
28772
|
})
|
|
28851
28773
|
)
|
|
28852
28774
|
});
|
|
28853
|
-
new
|
|
28775
|
+
new aws18.sqs.QueuePolicy("wraps-sms-events-queue-policy", {
|
|
28854
28776
|
queueUrl: config2.queueUrl,
|
|
28855
28777
|
policy: pulumi24.all([config2.queueArn, topic.arn]).apply(
|
|
28856
28778
|
([queueArn, topicArn2]) => JSON.stringify({
|
|
@@ -28869,7 +28791,7 @@ async function createSMSSNSResources(config2) {
|
|
|
28869
28791
|
})
|
|
28870
28792
|
)
|
|
28871
28793
|
});
|
|
28872
|
-
const subscription = new
|
|
28794
|
+
const subscription = new aws18.sns.TopicSubscription(
|
|
28873
28795
|
"wraps-sms-events-subscription",
|
|
28874
28796
|
{
|
|
28875
28797
|
topic: topic.arn,
|
|
@@ -28918,17 +28840,17 @@ async function createSMSDynamoDBTable() {
|
|
|
28918
28840
|
Service: "sms"
|
|
28919
28841
|
}
|
|
28920
28842
|
};
|
|
28921
|
-
return exists ? new
|
|
28843
|
+
return exists ? new aws18.dynamodb.Table(tableName, tableConfig, {
|
|
28922
28844
|
import: tableName,
|
|
28923
28845
|
customTimeouts: { create: "5m", update: "5m", delete: "5m" }
|
|
28924
|
-
}) : new
|
|
28846
|
+
}) : new aws18.dynamodb.Table(tableName, tableConfig, {
|
|
28925
28847
|
customTimeouts: { create: "5m", update: "5m", delete: "5m" }
|
|
28926
28848
|
});
|
|
28927
28849
|
}
|
|
28928
28850
|
async function deploySMSLambdaFunction(config2) {
|
|
28929
28851
|
const { getLambdaCode: getLambdaCode2 } = await Promise.resolve().then(() => (init_lambda(), lambda_exports));
|
|
28930
28852
|
const codeDir = await getLambdaCode2("sms-event-processor");
|
|
28931
|
-
const lambdaRole = new
|
|
28853
|
+
const lambdaRole = new aws18.iam.Role("wraps-sms-lambda-role", {
|
|
28932
28854
|
name: "wraps-sms-lambda-role",
|
|
28933
28855
|
assumeRolePolicy: JSON.stringify({
|
|
28934
28856
|
Version: "2012-10-17",
|
|
@@ -28945,11 +28867,11 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
28945
28867
|
Service: "sms"
|
|
28946
28868
|
}
|
|
28947
28869
|
});
|
|
28948
|
-
new
|
|
28870
|
+
new aws18.iam.RolePolicyAttachment("wraps-sms-lambda-basic-execution", {
|
|
28949
28871
|
role: lambdaRole.name,
|
|
28950
28872
|
policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
28951
28873
|
});
|
|
28952
|
-
new
|
|
28874
|
+
new aws18.iam.RolePolicy("wraps-sms-lambda-policy", {
|
|
28953
28875
|
role: lambdaRole.name,
|
|
28954
28876
|
policy: pulumi24.all([config2.tableName, config2.queueArn]).apply(
|
|
28955
28877
|
([tableName, queueArn]) => JSON.stringify({
|
|
@@ -28981,7 +28903,7 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
28981
28903
|
})
|
|
28982
28904
|
)
|
|
28983
28905
|
});
|
|
28984
|
-
const eventProcessor = new
|
|
28906
|
+
const eventProcessor = new aws18.lambda.Function(
|
|
28985
28907
|
"wraps-sms-event-processor",
|
|
28986
28908
|
{
|
|
28987
28909
|
name: "wraps-sms-event-processor",
|
|
@@ -29009,7 +28931,7 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
29009
28931
|
customTimeouts: { create: "5m", update: "5m", delete: "2m" }
|
|
29010
28932
|
}
|
|
29011
28933
|
);
|
|
29012
|
-
new
|
|
28934
|
+
new aws18.lambda.EventSourceMapping(
|
|
29013
28935
|
"wraps-sms-event-source-mapping",
|
|
29014
28936
|
{
|
|
29015
28937
|
eventSourceArn: config2.queueArn,
|
|
@@ -29025,7 +28947,7 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
29025
28947
|
return eventProcessor;
|
|
29026
28948
|
}
|
|
29027
28949
|
async function deploySMSStack(config2) {
|
|
29028
|
-
const identity = await
|
|
28950
|
+
const identity = await aws18.getCallerIdentity();
|
|
29029
28951
|
const accountId = identity.accountId;
|
|
29030
28952
|
let oidcProvider;
|
|
29031
28953
|
if (config2.provider === "vercel" && config2.vercel) {
|